最简单的内存泄漏检测器。
C++ 代码,展示如何跟踪内存使用情况以避免内存泄漏。
引言
当我重新开始使用 C++ 编写一些实验性的压缩算法时,我很恼火我丢失了用于跟踪内存使用的代码,而且似乎没有其他人发布过类似的东西。 基本原则是在全局范围内重写 new 和 delete,以便计算正在分配和释放的字节,但对于初学者来说,正确掌握这些机制是很棘手的,所以我认为我应该发布这些代码供其他人以后使用。
免责声明:下面显示的原始 new/delete 运算符是从网上复制粘贴的,但如何执行此操作是常识,我认为没有人可以声称对这 9 行代码拥有所有权。
背景
如前所述,在 C++ 程序中跟踪内存使用的基本原则是重写 new 和 delete 运算符,这样每当语言决定分配或释放一些内存时,我们都有机会运行一些代码。 我们不尝试跟踪对象,我们只是保留已使用的内存总量,程序完成后应恢复为零。
其中棘手的地方在于 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) 他们不会引入任何内存泄漏,试图使用 malloc 和 free。
就目前而言,此代码仅适用于调试小型项目。 它可以跟踪与您标记的内存一样多的对象,但当然在繁重负载下它会变得非常慢。 对我来说,更多的是能够检查一些简单的事情,因为我再次掌握了 C++ - 例如当您删除一个类时本地变量会发生什么,甚至只是何时调用 delete 与 delete[]。
我希望有人觉得这有用!
历史
首次发布。