65.9K
CodeProject 正在变化。 阅读更多。
Home

最简单的内存泄漏检测器。

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.17/5 (7投票s)

2009年10月18日

CPOL

3分钟阅读

viewsIcon

28291

downloadIcon

140

C++ 代码,展示如何跟踪内存使用情况以避免内存泄漏。

引言

当我重新开始使用 C++ 编写一些实验性的压缩算法时,我很恼火我丢失了用于跟踪内存使用的代码,而且似乎没有其他人发布过类似的东西。 基本原则是在全局范围内重写 newdelete,以便计算正在分配和释放的字节,但对于初学者来说,正确掌握这些机制是很棘手的,所以我认为我应该发布这些代码供其他人以后使用。

免责声明:下面显示的原始 new/delete 运算符是从网上复制粘贴的,但如何执行此操作是常识,我认为没有人可以声称对这 9 行代码拥有所有权。

背景

如前所述,在 C++ 程序中跟踪内存使用的基本原则是重写 newdelete 运算符,这样每当语言决定分配或释放一些内存时,我们都有机会运行一些代码。 我们不尝试跟踪对象,我们只是保留已使用的内存总量,程序完成后应恢复为零。

其中棘手的地方在于 C++ 没有告诉我们通过调用 delete 释放了多少内存。 事实上,这种实现是编译器/平台特定的。 因此,我的目标是找到一种方法来跟踪与每个指针关联的内存大小,但有一些限制

  • 您不能在 new/delete 期间(取消)分配任何内存,否则会导致无限递归。
  • 在结构准备好存储指针之前,您不能(取消)分配任何内存。
  • 我希望该用法可以从代码中的任何其他位置轻松获得。

使用代码

这是框架,您将其粘贴到 main.cpp 中。 您需要包含和 main 方法下面的两个方法。 这在 Dev C++ 中运行良好,并且应该在几乎任何环境中进行一些简单的修改。 您还可以下载包含 Dev C++ 的工作测试项目的代码。

// Includes that we need for the job. 
#include <cstdlib>
#include <exception>
#include <new>
 
// Entry point for the code. 
int main(int argc, char *argv[])
{

    // Your code starts here...
 

    system("PAUSE");
    return EXIT_SUCCESS;
}

// Allows us to switch it off later.
#define DEBUG_MEMORY
const int MAXLOCS = 256;

// Here is the actual storage for the data. 
int memUsage = 0;
int memLocs[MAXLOCS];
int memSizes[MAXLOCS];

#ifdef DEBUG_MEMORY
// Overridden new/delete so we can track memory usage.
void* operator new (size_t size)
{
    // First time call handling.
    if (memUsage == 0)
    {
        for (int x = 0; x < MAXLOCS; x++)
        {
            memLocs[x] = 0;
            memSizes[x] = 0;
        }
    }
 
    // Do the actual allocation.
    void *p=malloc(size); 

 
    // Memory counting.
    memUsage += size;

 
    // Pointer tracking. 
    for (int x = 0; x < MAXLOCS; x++)
    {
        if (memLocs[x] == 0)
        {
            memLocs[x] = (int) p;
            memSizes[x] = size;
            x = MAXLOCS;
        }
    }
 
    return p;
}
 
void operator delete (void *p)
{
    // Handy trap to have.
    if (p == NULL) throw std::bad_alloc();
    
    // Find the pointer and count the memory.
    for (int x = 0; x < MAXLOCS; x++)
    {
        if (memLocs[x] == (int) p)
        {
            memUsage -= memSizes[x];
            memLocs[x] = 0;
            memSizes[x] = 0;
            x = MAXLOCS;
        }
    }
 
    // Actually free the memory.    
    free(p); 
}
#endif

改进代码

如果要检查双重释放,如果找不到您尝试释放的指针,您可以简单地抛出异常。 我没有将此添加到代码中,因为它模糊了代码应该执行的操作,我试图以最简单的形式演示这一点。

如果有人能够提高所提供代码的效率,应该很容易,前提是 a) 他们不会引入(或他们以其他方式处理)任何会导致无限递归的动态分配,并且 b) 他们不会引入任何内存泄漏,试图使用 mallocfree

就目前而言,此代码仅适用于调试小型项目。 它可以跟踪与您标记的内存一样多的对象,但当然在繁重负载下它会变得非常慢。 对我来说,更多的是能够检查一些简单的事情,因为我再次掌握了 C++ - 例如当您删除一个类时本地变量会发生什么,甚至只是何时调用 delete 与 delete[]。

我希望有人觉得这有用!

历史

首次发布。

© . All rights reserved.