2012-11-15 91 views
4

我正在尝试编写一个小内存泄漏检测工具。如何在C++中编写一个小内存泄漏检测?

我的想法是跟踪我的应用程序 中的动态内存分配生命,以确定内存或未删除的内存的任何无效访问,这些访问可能导致我的应用程序在一段时间内使用核心。

我想写一个简单的界面来覆盖newdelete

而在我重写的new我想打印功能行地址等,然后调用标准new

有没有人已经试过这个?我不确定我是否可以从我的班级特定的新操作员调用标准新的。

+3

最简单的解决方案:cd/project/src; fgrep --silent -r -e“new”&&“编写更好的代码”' –

+0

与之关系密切,主要是针对Windows的,但奇怪的是,在阅读Raymond Chen的博客文章之后,您的问题出现在编写自己的分配器后:http ://blogs.msdn.com/b/oldnewthing/archive/2012/11/15/10368691.aspx – icabod

+1

[立即检测Windows上堆损坏错误的可能的重复。如何?](http://stackoverflow.com/questions/12724057/immediate-detection-of-heap-corruption-errors-on-windows-how) –

回答

0

在这个问题上我提出了一个特设的解决问题的方法:Immediate detection of heap corruption errors on Windows. How?

在一般情况下,你可以用这个代码替换您的newdelete

DWORD PageSize = 0; 

inline void SetPageSize() 
{ 
    if (!PageSize) 
    { 
     SYSTEM_INFO sysInfo; 
     GetSystemInfo(&sysInfo); 
     PageSize = sysInfo.dwPageSize; 
    } 
} 

void* operator new (size_t nSize) 
{ 
    SetPageSize(); 
    size_t Extra = nSize % PageSize; 
    nSize = nSize + (PageSize - Extra); 
    return Ptr = VirtualAlloc(0, nSize, MEM_COMMIT, PAGE_READWRITE); 
} 

void operator delete (void* pPtr) 
{ 
    MEMORY_BASIC_INFORMATION mbi; 
    VirtualQuery(pPtr, &mbi, sizeof(mbi)); 
    // leave pages in reserved state, but free the physical memory 
    VirtualFree(pPtr, 0, MEM_DECOMMIT); 
    DWORD OldProtect; 
    // protect the address space, so noone can access those pages 
    VirtualProtect(pPtr, mbi.RegionSize, PAGE_NOACCESS, &OldProtect); 
} 

确定的非法访问记忆。在进一步的讨论中,您会发现泄漏检测和其他内存错误检测的想法。

如果你想打电话全球newdelete,您可以使用::全局命名空间前缀:

return ::new(nSize); 
0

从类特定的operator new调用::operator new是很好的,很常见。您不能从替换版本::operator new中调用全局运算符new,因为如果将新运算符替换为新运算符,则旧运算符不存在。

+0

'mallow'存在;) – PiotrNycz

+0

@PiotrNycz - 'mallow'? '当然,'malloc'存在。这并没有改变这样一个事实,即如果您将新的全球运营商更换为新的,则不能再调用旧的运营商。 –

+0

我从电话打字,当然是'malloc'。你可以从新运算符new调用'malloc' ...对于旧运算符new - 我不确定,从来没有尝试过,但也许'dlsym(RTLD_NEXT,“name”)'可以用于检索旧运算符new - 需要用'nm'检查运算符new的实际名称(mangled name)...但正如我所说的,从来没有使用过dlsym()用于C++函数,只用于C函数... – PiotrNycz

0

上述方法听起来很合理。您可以对其进行增强,并将每个分配中的一些标识数据存储到某个数据结构中。这样,您可以在程序终止时跟踪所有未释放的内存,而无需检查所有分配/释放日志。

为了检测损坏,您可以在开始之前和结束之后使用填充来包装每个分配,并用一些预定义模式填充它。释放内存后,您可以验证模式是否仍然存在。这会给你一个检测腐败的好机会。

您可以调用全球new,其范围前缀为:::new