【C++】获取调用函数前后,进程所占物理内存的变化

本文介绍了一种使用C++实现的内存泄漏检测方法,通过自定义宏定义和类来监控进程的物理内存变化,并在特定条件下输出警告信息。适用于Windows和Linux平台。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

包含 acheckmemleak.h 头文件,然后使用 CHECK_MEMLEAK 宏定义就行。具体看如下代码:
#ifndef ACHECKMEMLEAK_H
#define ACHECKMEMLEAK_H

#define CHECK_MEMLEAK(nChangeByte) ACheckMemLeak aCheckMemLeak(nChangeByte, __FILE__, __FUNCTION__, __LINE__);

#include <QString>
#include <QDebug>

#ifdef Q_OS_WIN32
    #include <windows.h>
    #include <psapi.h>
#elif defined(Q_OS_LINUX)
    #include <sys/types.h>
    #include <unistd.h>
    #include <sstream>
    #include <fstream>
    #include <string>
    #include <QFile>
#endif

class ACheckMemLeak
{
public:
    explicit ACheckMemLeak(int nChangeByte, const char* pFileName, const char* pFuncName, int nFileLineNo)
        : m_nChangeByte(nChangeByte)
        , m_sFileName(pFileName)
        , m_sFuncName(pFuncName)
        , m_nFileLineNo(nFileLineNo)
    {
        if(0 != m_llMemStart)
        {
            long long llMemEnd = getProcessPhyMem();
            long long llChangeByte = llMemEnd - m_llMemStart;
            qDebug() << QString("[CheckMemLeak-%1-%2-%3]Start:%4B,End:%5B,Change:%6B=%7KB=%8MB)")
                        .arg(m_sFileName.c_str()).arg(m_sFuncName.c_str()).arg(m_nFileLineNo)
                        .arg(m_llMemStart).arg(llMemEnd)
                        .arg(llChangeByte).arg(llChangeByte/1024).arg(llChangeByte/1024/1024);
            if(llChangeByte > m_nChangeByte)
                qWarning() << "Maybe CheckMemLeak...";
            m_llMemStart = llMemEnd;
        }
        else
            m_llMemStart = getProcessPhyMem();
    }

    ~ACheckMemLeak()
    {
        long long llMemEnd = getProcessPhyMem();
        long long llChangeByte = llMemEnd - m_llMemStart;
        qDebug() << QString("[CheckMemLeak-%1-%2-%3]Start:%4B,End:%5B,Change:%6B=%7KB=%8MB)")
                    .arg(m_sFileName.c_str()).arg(m_sFuncName.c_str()).arg(m_nFileLineNo)
                    .arg(m_llMemStart).arg(llMemEnd)
                    .arg(llChangeByte).arg(llChangeByte/1024).arg(llChangeByte/1024/1024);
        if(llChangeByte > m_nChangeByte)
            qWarning() << "Maybe CheckMemLeak...";
        m_llMemStart = llMemEnd;
    }

private:
    long long getProcessPhyMem()
    {
    #ifdef Q_OS_WIN32
        PROCESS_MEMORY_COUNTERS pmc;
        if (GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc)))
            return pmc.WorkingSetSize;
    #elif defined(Q_OS_LINUX)
        // 结果*4*1024是因为以内存页4KB为单位的.
        uid_t pid = getpid();
        /* C语言方式
        char fileName[100] = {0};
        sprintf(fileName, "/proc/%d/statm", pid);
        FILE* pFile = NULL;
        pFile = fopen(fileName, "r");
        if(NULL == pFile)
            return 0;
        char buff[255] = {0};
        if(NULL != fgets(buff, 255, (FILE*)pFile))
        {
            char *pNeedContent = strtok(buff, " ");
            pNeedContent = strtok(NULL, " ");
            return atoll(pNeedContent)*4*1024;
        }*/

        /* C++方式
        std::stringstream strStream;
        strStream << "/proc/" << pid << "/statm";
        std::string sFileName = strStream.str();
        std::ifstream f(sFileName.c_str(), std::ios::in);
        if(false == f.is_open())
            return 0;
        std::string sContent;
        if(getline(f, sContent))
        {
            char cContentArr[sContent.length()+1];
            bzero(cContentArr, sizeof(cContentArr));
            strcpy(cContentArr, sContent.c_str());
            char* pNeedContent = strtok(cContentArr, " ");
            pNeedContent = strtok(NULL, " ");
            return atoll(pNeedContent)*4*1024;
        }*/

        // Qt方式
        QFile f(QString("/proc/%1/statm").arg(QString::number(pid)));
        if (false == f.open(QIODevice::ReadOnly))
            return 0;
        QByteArray ba = f.readAll();
        f.close();
        QByteArrayList lst = ba.split(' ');
        return lst.at(1).toLongLong()*4*1024;

    #endif
        return 0;
    }

private:
    int m_nChangeByte;
    std::string m_sFileName;
    std::string m_sFuncName;
    int m_nFileLineNo;

    static long long m_llMemStart;
};

long long ACheckMemLeak::m_llMemStart = 0;

#endif // ACHECKMEMLEAK_H

下面是测试的代码:

#include <QCoreApplication>
#include <QDebug>
#include <QThread>
#include "acheckmemleak.h"

void func()
{
    for(int i=0; i<1000; i++)
        int *p = new int(i);
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    for(int i=0; i<10; i++)
    {
        {
            CHECK_MEMLEAK(0)
            func();
        }
        QThread::sleep(1);
    }

    return a.exec();
}
// 注意链接库文件,下面是 Qt 方式(在.Pro文件加上)
windows{
    LIBS += -lpsapi
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值