美文网首页
自己写内存泄漏工具

自己写内存泄漏工具

作者: 龙翱天际 | 来源:发表于2018-07-04 09:13 被阅读32次

简述

内存泄露一直是一个C++开发程序员需要重点关注的问题。虽然在C++11引入智能指针后,内存泄露有了很大的改善,但未使用智能指针,用错的地方或循环引用等情况下,还是会有很多内存泄露的产生。
在windows系统下用的最多的第三方内存泄漏工具主要有:

  • vld
    此工具是通过将库引入工程来做检测,具有侵入性。默认只能检测Debug版,Release版下使用,请点击这里
    类似的原理可以通过自己重写malloc,free等函数和重载new,delete运算符,然后在程序中,不引用系统头文件,而引用我们重写的头文件让相应的函数和运算符优先进到我们的函数来做内存泄漏检测或其他的坏事
  • UMDH
    使用方法,请点击这里

Detours

Detours是一个用于重新路由Win32 api的软件包。由于重新路由的是应用层API,所以它是一个应用层Hook机制。
如果某个库重新路由的是驱动层API,则就是驱动层Hook机制,可以监控文件读写,注册表操作等。

编译Detours

该库的编译方法,请点击这里

Detours的作用

通过该库,我们可以截获任何一个API,让程序进入相应API前,先进入我们的函数,我们可以改写对应的参数,终止调用等,来达到我们想要的目的。这其中就包括我们要做的内存泄露检测的功能。

内存泄露检测关键项

函数Hook的时机,可以在动态库加载时就启动Hook,在程序退出时结束Hook,也可以由用户指定。

  • 启动Hook
    DetourTransactionBegin();
    DetourUpdateThread(GetCurrentThread());
    //VS2010
    g_pOldMalloc100 = (PFN_MALLOC)DetourFindFunction("msvcr100.dll", "malloc");
    DetourAttach(&(PVOID&)g_pOldMalloc100, MyMalloc100);

    //VS2013
    g_pOldMalloc120 = (PFN_MALLOC)DetourFindFunction("msvcr120.dll", "malloc");
    DetourAttach(&(PVOID&)g_pOldMalloc120, MyMalloc120);

    DetourTransactionCommit();
  • 结束Hook
    DetourTransactionBegin();
    DetourUpdateThread(GetCurrentThread());
    DetourDetach(&(PVOID&)g_pOldMalloc100, MyMalloc100);
    DetourDetach(&(PVOID&)g_pOldMalloc120, MyMalloc120);
    DetourTransactionCommit();
  • 重写的malloc函数
void* __cdecl MyMalloc100(
    _In_ _CRT_GUARDOVERFLOW size_t _Size
)
{
    void *pVoid = g_pOldMalloc100(_Size);
    char s[MAX_PATH] = { 0 };
    sprintf(s, "MyMalloc100, Malloc: %0x, Size: %d Bytes\r\n", pVoid, _Size);
    //OutputDebugStringA(s);
    //要打印调用堆栈,就不能用自动分配内存的stl对象,或自己new(malloc)空间,否则会陷入死循环
    //可以考虑在栈空间中申请内存,然后写入文件中
    MemoryLeaker *pLeaker = &g_array[g_nIndex];
    g_nIndex++;
    pLeaker->pAddress = pVoid;
    pLeaker->nSize = _Size;
    //先将堆栈指针保存下来,等到退出Hook后,再获取堆栈信息,如果再此时获取,则会陷入死循环
    pLeaker->frames = CaptureStackBackTrace(0, MAX_STACK_FRAMES, pLeaker->pStack, NULL);
    return pVoid;
}
  • 打印堆栈
    void *pStack[MAX_STACK_FRAMES];

    WORD frames = CaptureStackBackTrace(0, MAX_STACK_FRAMES, pStack, NULL);

    std::ostringstream oss;
    oss << "stack traceback: " << std::endl;
    for (WORD i = 0; i < frames; ++i) {
        DWORD64 address = (DWORD64)(pStack[i]);

        DWORD64 displacementSym = 0;
        char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
        PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
        pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
        pSymbol->MaxNameLen = MAX_SYM_NAME;

        DWORD displacementLine = 0;
        IMAGEHLP_LINE64 line;
        //SymSetOptions(SYMOPT_LOAD_LINES);  
        line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);

        if (SymFromAddr(m_hProcess, address, &displacementSym, pSymbol)
            && SymGetLineFromAddr64(m_hProcess, address, &displacementLine, &line)) {
            oss << "\t" << pSymbol->Name << " at " << line.FileName << ":" << line.LineNumber << "(0x" << std::hex << pSymbol->Address << std::dec << ")" << std::endl;
        }
        else {
            oss << "\terror: " << GetLastError() << std::endl;
        }
    }
    return oss.str();

注意事项

  • Hook后,会检测到所有通过exe申请的内存,包括第三方库或微软的API。
  • 在Hook的malloc等函数中,尽量不要动态内存分配,否则可能导致循环嵌套,最后搞崩程序。
  • 打印详细堆栈需要在退出Hook后。

相关文章

  • 自己写内存泄漏工具

    简述 内存泄露一直是一个C++开发程序员需要重点关注的问题。虽然在C++11引入智能指针后,内存泄露有了很大的改善...

  • Learn C the Hard Way Ex4:Using a

    c语言代码检查工具:splintLinux 内存泄漏检查工具:Valgrindmac 内存泄漏检查工具:Addre...

  • Android内存泄漏场景及解决方法

    本文包括以下内容: 内存泄漏原理 Android内存泄漏发生的情况 检测内存泄漏的工具、方法 如何避免内存泄漏 更...

  • 性能优化——内存泄漏(3)代码分析篇

    内存泄漏系列文章:性能优化——内存泄漏(1)入门篇性能优化——内存泄漏(2)工具分析篇性能优化——内存泄漏(3)代...

  • 性能优化——内存泄漏(2)工具分析篇

    内存泄漏系列文章:性能优化——内存泄漏(1)入门篇性能优化——内存泄漏(2)工具分析篇性能优化——内存泄漏(3)代...

  • 性能优化——内存泄漏(1)入门篇

    内存泄漏系列文章:性能优化——内存泄漏(1)入门篇性能优化——内存泄漏(2)工具分析篇性能优化——内存泄漏(3)代...

  • 一篇文章学会定位内存泄漏

    在日常开发中,不可避免的会碰到内存泄漏问题,本片文章作为记录自己在工作中如何使用工具发现内存泄漏,定位内存泄漏。 ...

  • Xcode调试工具

    一.静态内存分析工具 编译阶段查找内存泄漏等问题 1.常见内存泄漏问题 常见的内存泄漏除了循环引用,CoreFou...

  • Android 优化一: Leakcanary检测内存泄漏汇总

    Leakcanary检测内存泄漏汇总目录介绍:1.什么是内存泄漏2.内存泄漏造成什么影响3.内存泄漏检测的工具有哪...

  • leakcanery2源码

    LeakCanary是Android上用于检查内存泄漏的工具,LeakCanary大大减少因内存泄漏导致的内存溢出...

网友评论

      本文标题:自己写内存泄漏工具

      本文链接:https://www.haomeiwen.com/subject/kurjuftx.html