所以这首先是一个家庭作业项目。我的整个程序正在运行,它是一个处理动态内存分配的中间/高级中介项目。我无法弄清楚如何用正常输出显示行号。我试图在堆栈上查看有关此主题的其他问题,但我似乎无法弄清楚有助于我的理由。有关如何显示行号的任何建议吗?
这是我的"LeakWatcher.cpp"
#ifndef IMWATCHINGYOULEAK
#define IMWATCHINGYOULEAK
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#ifdef _DEBUG
inline void* operator new(size_t nSize, const char * lpszFileName, int nLine)
{ return ::operator new(nSize, 1, lpszFileName, nLine); }
inline void __cdecl operator delete(void * _P, const char * lpszFileName, int nLine)
{ ::operator delete(_P, _NORMAL_BLOCK, lpszFileName, nLine); }
#define DEBUG_NEW new( __FILE__, __LINE__)
#define MALLOC_DBG(x) _malloc_dbg(x, 1, __FILE__, __LINE__);
#define malloc(x) MALLOC_DBG(x)
#define new DEBUG_NEW
#endif // _DEBUG
#endif // #include guard
我的main()
int main()
{
_CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT );
_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT );
_CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT );
try
{
Directory().Run();
}
catch ( ... )
{
cout << "Uncaught Exception" << endl;
}
_CrtDumpMemoryLeaks();
return 0;
}
答案 0 :(得分:1)
根据您的代码确实发生的事情就是这个。您说您将所有调试宏放入LeakWatcher.cpp
而不是LeakWatcher.h
。我怀疑这是你的问题。
使用LeakWatcher.h
中当前拥有的所有内容创建LeakWatcher.cpp
。您不需要LeakWatcher.cpp
,因此您应该可以将其删除。现在在所有#include "LeakWatcher.h"
个文件的顶部使用.cpp
。所以它看起来像下面这样。
档案 LeakWatcher.h
#ifndef IMWATCHINGYOULEAK
#define IMWATCHINGYOULEAK
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#ifdef _DEBUG
inline void* operator new(size_t nSize, const char * lpszFileName, int nLine)
{ return ::operator new(nSize, 1, lpszFileName, nLine); }
inline void __cdecl operator delete(void * _P, const char * lpszFileName, int nLine)
{ ::operator delete(_P, _NORMAL_BLOCK, lpszFileName, nLine); }
#define DEBUG_NEW new( __FILE__, __LINE__)
#define MALLOC_DBG(x) _malloc_dbg(x, 1, __FILE__, __LINE__);
#define malloc(x) MALLOC_DBG(x)
#define new DEBUG_NEW
#endif // _DEBUG
#endif // #include guard
然后在 test.cpp 这样的文件中你可以这样做(类似于你的测试代码):
#include "LeakWatcher.h"
int main()
{
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDOUT);
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT);
new int[40]; // This should be a memory leak
_CrtDumpMemoryLeaks(); // This should dump with line numbers and file names
return 0;
}
当然,只有在构建项目的debug
版本时,这才有效。
为了获得覆盖这些堆例程的其他一些见解,我发现这个MSDN Article很有价值。
答案 1 :(得分:0)
我认为你问的是跟踪已经分配但未被释放的内存的实际算法。
为了产生诊断输出,跟踪内存分配请求来源的典型方法如下:
假设您要跟踪来电者请求的n_bytes
内存。
分配n_bytes
+ sizeof(const char *)+ sizeof(int)。
将 FILE 和 LINE 存储在已分配内存的第一部分中,并将剩余的已分配内存返回到所谓的已分配内容。
这样的事情:
struct hdr {
const char *file;
int line;
};
void *my_allocation_request(const char *file, int line, size_t nbytes)
{
struct hdr *p=(struct hdr *)malloc(nbytes+sizeof(hdr));
p->file=file;
p->line=line;
// Here be dragons
return (void *)(p+1);
}
(大概,你的new
运营商会受到惩罚。)
类似,当某些东西想要释放内存块时
void my_deallocation_request(char *p)
{
struct hdr *h=reinterpret_cast<hdr *>(p+1);
// Here be dragons
free(h);
}
在此可以作为最终解决方案之前,您还需要编写更多代码,这些代码将进入“Here be dragons”部分,我想您可能会自己解决这个问题:
A)取出每个新分配的内存并将其放在某种列表中(龙的第一个位置)。
B)从某种列表中删除分配的内存(龙的第二个位置)。
然后,在程序结束时,您可以浏览列表中剩余的任何内容。这将是你泄露的内存,你将拥有文件和分配它的行号。
请注意,您可能希望手动实现未发布内存块的链接列表。使用一些标准容器可能会导致无限循环,因为容器非常合理地期望能够为自己的内容分配内存,这将循环回你自己的新/删除拦截,这将要求容器分配更多的内存,它将循环回你自己的新/删除拦截等...
这里可能存在一些关于已分配内存对齐的特定于实现的问题,但这不太可能,而且现在可能会忽略这种分裂。