C++内存泄漏未正确显示
C++ Memory Leak not properly showing
我正在使用 _CrtDumpMemoryLeaks(); 从 stdlib.h 和 crtdbg.h 来检测内存泄漏,但我注意到我的代码中有一些奇怪的东西。
如果我这样做:
int _tmain(int argc, _TCHAR* argv[])
{
MyClass* myClass = new MyClass();
_CrtDumpMemoryLeaks(); //I get a memory leak warning
}
但是,如果我这样做:
class MyClass
{
public:
char* NewChar();
};
char* MyClass::NewChar()
{
char* test = new char[100];
return test;
}
MyClass myClass; //Globally declared
int _tmain(int argc, _TCHAR* argv[])
{
char* charPointer = myClass.NewChar();
_CrtDumpMemoryLeaks(); //No warnings
}
我不应该收到警告,因为我的程序退出了(紧跟在 _CrtDumpMemoryLeaks()之后)并且仍然有一个没有删除的新字符?
如何检测这些内存泄漏?
另外,使用上面的相同示例,如果我添加代码:
char* anotherPointer = charPointer; //previously filled
delete[] anotherPointer;
这会从类内部删除新字符以防止内存泄漏,还是我也应该在 charPointer 上调用 delete?
如果您想捕获(或捕获)全局对象泄漏,请尝试在 main 的开头_CRTDBG_LEAK_CHECK_DF设置 CRT 调试标志。该标志强制在全局析构函数之后转储检测到的泄漏。
要回答您的问题:
我不应该收到警告,因为我的程序退出了(紧跟在 _CrtDumpMemoryLeaks() 之后)并且仍然有一个没有删除的新字符?
定义"警告"。对_CrtDumpMemoryLeaks()
的呼吁应该抛弃当时未完成的任何内容。之后退出的程序不会执行另一个转储,除非配置为这样做。
如何检测这些内存泄漏?
如果您使用的是调试 CRT 并正确设置了_Crt
配置,则应正确检测它们,这通常是默认的。
以下代码将 _Crt
转储系统设置为在最终退出之前(main()
完成并销毁全局静态数据之后)按需转储所有对象。
class MyLeak
{
public:
MyLeak() { new unsigned char[1024]; }
char * NewChar() { return new char[1024]; }
};
MyLeak myLeak;
int main(int argc, char *argv[])
{
int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
tmpFlag |= _CRTDBG_LEAK_CHECK_DF;
_CrtSetDbgFlag(tmpFlag);
_CrtMemState ms = {0};
_CrtMemCheckpoint(&ms);
char *ptr = myLeak.NewChar();
_CrtMemDumpAllObjectsSince(&ms);
OutputDebugString("Exiting main()n");
return EXIT_SUCCESS;
}
调试输出日志
Dumping objects ->
{69} normal block at 0x000000000048B800, 1024 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.
Exiting main()
Detected memory leaks!
Dumping objects ->
{69} normal block at 0x000000000048B800, 1024 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
{68} normal block at 0x000000000048B390, 1024 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.
请注意,第一个转储只记录内部分配,因为我使用了检查点,然后是转储自调用。第二个转储(在main()
完成后调用)仍然记录它们,因为它们都非常出色。
在动态分配(授予来自全局内存空间中的对象,但与分配无关,它只是代码分配内存并将其返回给您)后,您是泄漏转储看起来不正确。您应该获得自程序启动以来所有未完成 CRT 分配的对象转储以及任何_CrtDumpMemoryLeaks()
调用。
想一想。全局变量myClass
具有静态存储持续时间。当程序终止时,它将在main
的闭合大括号后被销毁。 _CrtDumpMemoryLeaks
() 无法肯定地检测到泄漏,因为尚未(正确)调用MyClass
的析构函数。
自从我的程序退出以来,我不应该收到警告吗(右after_CrtDumpMemoryLeaks())
是的,您应该收到警告,但不是因为退出,...
还有一个新的字符没有被删除?
。但正因为如此,即因为仍然有一个动态分配的 char 数组没有被删除。
您如何检测这些内存泄漏?
确定您用_DEBUG #defined编译了该程序吗?如果你这样做了,它应该被检测到。(现在无法检查自己,并且已经很久没有使用过这个了,所以我真的不能保证这一点。
另外,使用上面的相同示例,如果我添加代码:
char* anotherPointer = charPointer; //previously filled
删除[]另一个指针;这会从类内部删除新字符以防止内存泄漏,还是我也应该在 charPointer 上调用 delete?
这将删除动态分配的字符数组。在此charPointer
之后是一个悬空指针,不得再使用它 - 既不能取消引用,也不能删除[]'d。 (这同样适用于anotherPointer
。 不允许再次删除已删除的数组,无论是通过同一指针还是其他变量,这都会导致未定义的行为。
您是否与调试库链接?否则,您将不会收到有关未释放内存块的消息。提示:使用/MDd 选项。
请注意,与函数名称所暗示的相反,它所做的只是打印尚未释放的内存块列表。通过在 main() 末尾调用它,您可以让它报告您明确分配但未显式释放的块。因此,如果您动态分配了单例对象,它们将被报告为泄漏,而您可能非常合法地使用通过 _atexit() 机制连接的函数释放它们。
- 为什么C++总是显示十六进制内存地址,而不仅仅是整数?
- 直接显示手动图形内存泄漏
- 了解 Linux 虚拟内存:valgrind 的 massif 输出显示了有和没有 --pages-as-heap 的主要差异
- C++程序什么都不做,但瓦尔格林德显示内存分配
- Valgrind 在 std::make_unique 中显示内存泄漏
- 无法在 Opencv 中显示图像导致内存位置
- 在 SFML 中不使用动态内存时显示白色纹理代替实际纹理
- Windows API SIZE_T在内存和控制台中不显示相同的值
- free -m 没有显示正确的数据,我使用了 1GB 的持久内存,但它只显示使用了 100kb
- 如何显示在堆上创建的内存的地址
- 在 QML 场景中显示内存中的网格
- Valgrind 在主机名命令输出中显示内存泄漏
- 终端中未显示内存地址(参考)
- 为什么 Go 不显示内存重新排序?
- 可能存在SDL_Net问题和使用 openCV 显示内存中的 YUV 相机帧
- C ++ Valgrind 在 Hello World 中显示内存泄漏
- 尝试使用while循环取消分配向量,任务管理器显示内存使用正在增加
- Kcachegrind显示内存未对齐
- top可能显示内存使用不正确
- Valgrind 在 unittest-cpp 库中显示内存泄漏