If the existing code is not modified, memory leakage is detected when the program exits.

Source: Internet
Author: User

(2.05.19 supplement:

Although the-rdynamic option greatly improves readability, it is still difficult to locate a line of leaked code based on the binary address;

In this case, use objdump-s exefile)

It is easy to detect memory leakage in windows. After all, msdn is powerful and provides many methods. If you are interested, you can view the VLD source code;

A few days ago, I accidentally found from the man document that Linux could hook malloc; so I wrote the following code to detect memory leaks;

The existing program code only needs to be compiled with the linux_vld.o file, and the memory leakage status will be printed upon exit;

For the following files, you can obtain the o file from G ++-C linux_vld.cc;

#ifndef LINUX_VLD_H#define LINUX_VLD_H#include <stdlib.h>#include <malloc.h>#endif

#include <map>#include <vector>#include <string>#include <execinfo.h>#include <cxxabi.h>#include "linux_vld.h"static void *(*old_malloc_hook)(size_t, const void*);static void (*old_free_hook)(void*, const void*);static void *(*old_realloc_hook)(void*, size_t, const void*);static void ReportMemoryLeak(void);static void MyHookInit(void);static void MyHookUnInit(void);static void* MyMallocHook(size_t, const void* );static void* MyReallocHook(void* , size_t , const void* );static void  MyFreeHook(void* , const void* );typedef struct{    std::size_t  size;    std::vector<std::string>  stackinfo;} NODE;static  std::map<void*, NODE>   s_ptrContainer;typedef std::map<void*, NODE>::iterator ITER;namespace{    class HookGuard    {    private:        static HookGuard sm_guard;        HookGuard();    public:        ~HookGuard();    };    // Hook init in constructor    HookGuard   HookGuard::sm_guard;    HookGuard::HookGuard()    {        __malloc_initialize_hook = &MyHookInit;        atexit(&ReportMemoryLeak);    }    HookGuard::~HookGuard()     {        MyHookUnInit();    }} // end namespacestatic void* MyMallocHook(size_t size, const void* caller){    MyHookUnInit();    void* pResult = ::malloc(size);    if (NULL != pResult)    {        NODE    node;        void*   arr[32];        int     nFrames= ::backtrace(arr, sizeof(arr)/sizeof(arr[0]));        char** strings = ::backtrace_symbols(arr, nFrames);        if (NULL != strings)        {            node.stackinfo.reserve(nFrames);            for (int i = 0; i < nFrames; ++ i)            {                node.stackinfo.push_back(strings[i]);            }            ::free(strings);        }        node.size = size;        s_ptrContainer[pResult] = node;    }    MyHookInit();    return  pResult;}static void* MyReallocHook(void* ptr, size_t size, const void* caller){    MyHookUnInit();    const bool isFree(ptr != NULL && size == 0);    void* pResult = ::realloc(ptr, size);    if (NULL != pResult)    {        NODE    node;        void*   arr[32];        int     nFrames= ::backtrace(arr, sizeof(arr)/sizeof(arr[0]));        char** strings = ::backtrace_symbols(arr, nFrames);        if (NULL != strings)        {            node.stackinfo.reserve(nFrames);            for (int i = 0; i < nFrames; ++ i)            {                node.stackinfo.push_back(strings[i]);            }            ::free(strings);        }        node.size = size;        s_ptrContainer[pResult] = node;    }    else if (isFree)     {        ITER  it = s_ptrContainer.find(ptr);        if (it != s_ptrContainer.end())        {            s_ptrContainer.erase(ptr);        }    }        MyHookInit();    return  pResult;}static void MyFreeHook(void* ptr, const void* caller){    if (NULL == ptr)        return ;    MyHookUnInit();    ITER  it = s_ptrContainer.find(ptr);    if (it != s_ptrContainer.end())    {        s_ptrContainer.erase(ptr);    }    ::free(ptr);    MyHookInit();}static void MyHookInit(void){    old_malloc_hook = __malloc_hook;    old_realloc_hook = __realloc_hook;    old_free_hook = __free_hook;    __malloc_hook = &MyMallocHook;    __realloc_hook = &MyReallocHook;    __free_hook = &MyFreeHook;}static void MyHookUnInit(void){    __malloc_hook = old_malloc_hook;    __realloc_hook = old_realloc_hook;    __free_hook   = old_free_hook;}///////////// TESTstatic void  ReportMemoryLeak(void){    if (s_ptrContainer.empty())    {        printf("DEBUG No Memory leak\n");        return;    }    ITER  it(s_ptrContainer.begin());    while (it != s_ptrContainer.end())    {        printf("================================================\n");        printf("DEBUG Memory leak at %p, size =[%lu]bytes\n", it->first, it->second.size);        std::vector<std::string>::const_iterator  stackiter(it->second.stackinfo.begin());        std::vector<std::string>::const_iterator  end(it->second.stackinfo.end());        int   frameNo = 0;        while (stackiter != end)        {            std::string  mangleName = (*stackiter).c_str();            std::size_t start  = mangleName.find('(');            std::size_t end    = mangleName.find('+', start);            if (std::string::npos == start || std::string::npos == end)            {                printf("Frame[%d]: %s\n", frameNo, (*stackiter).c_str());            }            else            {                ++ start;                int status = 0;                char* name = abi::__cxa_demangle(mangleName.substr(start, end - start).c_str(), NULL, 0, &status);                if (0 == status)                {                    printf("Frame[%d]: %s\n", frameNo, name);                    ::free(name);                }                else                {                    printf("Frame[%d]: %s\n", frameNo, (*stackiter).c_str());                }            }            ++ frameNo;            ++ stackiter;        }        ++ it;    }}

The following is a test file. CC. The compilation command is as follows:

G ++-rdynamic file. CC linux_vld.o

    #include <stdlib.h>            void* TestMalloc()      {          return ::malloc(12);      }            void* TestRealloc(void* ptr)      {          return ::realloc(ptr, 128);      }                  int main(int ac, char* av[])      {          void* ptr = TestMalloc();          ::free(ptr);          ptr = TestMalloc();          ptr = NULL;          ptr = TestRealloc(ptr);      }  

When the program exits, the output is as follows:

================================================  DEBUG Memory leak at 0x50c010, size =[12]bytes  Frame[0]: ./a.out [0x405ee5]  Frame[1]: TestMalloc()  Frame[2]: ./a.out(main+0x26) [0x4056fa]  Frame[3]: /lib64/libc.so.6(__libc_start_main+0xf4) [0x2ab4fc643154]  Frame[4]: ./a.out(__gxx_personality_v0+0x69) [0x405619]  ================================================  DEBUG Memory leak at 0x50c160, size =[128]bytes  Frame[0]: ./a.out [0x405d09]  Frame[1]: TestRealloc(void*)  Frame[2]: ./a.out(main+0x3b) [0x40570f]  Frame[3]: /lib64/libc.so.6(__libc_start_main+0xf4) [0x2ab4fc643154]  Frame[4]: ./a.out(__gxx_personality_v0+0x69) [0x405619]  

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.