zoukankan      html  css  js  c++  java
  • Memory leak detector(C++)

    Memory leak detector ( C++)

    This is a simple solution for memory leak detector.

    For any C++ software source under windows, please follow these steps:


       1. You need to put MemoryTracker.h and MemoryAllocateTracker.h into include folder, and force all *.cpp file to include MemoryTracker.h first(when using MVS C++/Using precompiled headers, we usually include it within stdafx.h, and remove all MVS C++ generated DEBUG_NEW if exists);

       2. Besides, modify the log file location(which is now c:\temp\) in MemoryAllocateTracker.cpp, and rebuild the version of MemoryAllocateTracker.dll;

       3. Also make sure no other 'replace new' exists in your C++ source;

      
    For any issues, please feel free to send email to health_163@163.com.

    MemoryTracker.h

    #pragma once

    #ifdef _DEBUG
    #pragma comment(lib, "MemoryAllocateTracker.lib")
    #include
    "MemoryAllocateTracker.h"

    #ifdef
    new
    #undef new
    #endif


    inline
    void * __cdecl operator new(size_t size, const char* file, int line)
    {
    return MemoryAllocateTracker::GetInstance().re_malloc_dbg(size, _NORMAL_BLOCK, file, line);
    }
    inline
    void * __cdecl operator new[](size_t size, const char* file, int line)
    {
    return operator new (size, file, line);
    }
    inline
    void __cdecl operator delete(void * ptr)
    {
    MemoryAllocateTracker::GetInstance().re_free_dbg(ptr, _NORMAL_BLOCK);
    }
    inline
    void __cdecl operator delete[](void * ptr)
    {
    delete ptr;
    }

    #ifdef DEBUG_NEW
    #undef DEBUG_NEW
    #endif

    #define DEBUG_NEW new (__FILE__, __LINE__)
    #define new DEBUG_NEW

    #ifdef malloc
    #undef malloc
    #endif
    #define malloc(s) MemoryAllocateTracker::GetInstance().re_malloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__)

    #ifdef calloc
    #undef calloc
    #endif
    #define calloc(c, s) MemoryAllocateTracker::GetInstance().re_calloc_dbg(c, s, _NORMAL_BLOCK, __FILE__, __LINE__)

    #ifdef realloc
    #undef realloc
    #endif
    #define realloc(p, s) MemoryAllocateTracker::GetInstance().re_realloc_dbg(p, s, _NORMAL_BLOCK, __FILE__, __LINE__)
    //#define _recalloc(p, c, s) _recalloc_dbg(p, c, s, _NORMAL_BLOCK, __FILE__, __LINE__)
    //#define _expand(p, s) _expand_dbg(p, s, _NORMAL_BLOCK, __FILE__, __LINE__)

    #ifdef free
    #undef free
    #endif
    #define free(p) MemoryAllocateTracker::GetInstance().re_free_dbg(p, _NORMAL_BLOCK)

    //#define _msize(p) _msize_dbg(p, _NORMAL_BLOCK)
    //#define _aligned_msize(p, a, o) _aligned_msize_dbg(p, a, o)
    //#define _aligned_malloc(s, a) _aligned_malloc_dbg(s, a, __FILE__, __LINE__)
    //#define _aligned_realloc(p, s, a) _aligned_realloc_dbg(p, s, a, __FILE__, __LINE__)
    //#define _aligned_recalloc(p, c, s, a) _aligned_recalloc_dbg(p, c, s, a, __FILE__, __LINE__)
    //#define _aligned_offset_malloc(s, a, o) _aligned_offset_malloc_dbg(s, a, o, __FILE__, __LINE__)
    //#define _aligned_offset_realloc(p, s, a, o) _aligned_offset_realloc_dbg(p, s, a, o, __FILE__, __LINE__)
    //#define _aligned_offset_recalloc(p, c, s, a, o) _aligned_offset_recalloc_dbg(p, c, s, a, o, __FILE__, __LINE__)
    //#define _aligned_free(p) _aligned_free_dbg(p)
    //
    //#define _malloca(s) _malloca_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__)
    //#define _freea(p) _freea_dbg(p, _NORMAL_BLOCK)
    //
    //#define _strdup(s) _strdup_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__)
    //#define _wcsdup(s) _wcsdup_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__)
    //#define _mbsdup(s) _strdup_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__)
    //#define _tempnam(s1, s2) _tempnam_dbg(s1, s2, _NORMAL_BLOCK, __FILE__, __LINE__)
    //#define _wtempnam(s1, s2) _wtempnam_dbg(s1, s2, _NORMAL_BLOCK, __FILE__, __LINE__)
    //#define _fullpath(s1, s2, le) _fullpath_dbg(s1, s2, le, _NORMAL_BLOCK, __FILE__, __LINE__)
    //#define _wfullpath(s1, s2, le) _wfullpath_dbg(s1, s2, le, _NORMAL_BLOCK, __FILE__, __LINE__)
    //#define _getcwd(s, le) _getcwd_dbg(s, le, _NORMAL_BLOCK, __FILE__, __LINE__)
    //#define _wgetcwd(s, le) _wgetcwd_dbg(s, le, _NORMAL_BLOCK, __FILE__, __LINE__)
    //#define _getdcwd(d, s, le) _getdcwd_dbg(d, s, le, _NORMAL_BLOCK, __FILE__, __LINE__)
    //#define _wgetdcwd(d, s, le) _wgetdcwd_dbg(d, s, le, _NORMAL_BLOCK, __FILE__, __LINE__)
    //#define _getdcwd_nolock(d, s, le) _getdcwd_lk_dbg(d, s, le, _NORMAL_BLOCK, __FILE__, __LINE__)
    //#define _wgetdcwd_nolock(d, s, le) _wgetdcwd_lk_dbg(d, s, le, _NORMAL_BLOCK, __FILE__, __LINE__)
    //#define _dupenv_s(ps1, size, s2) _dupenv_s_dbg(ps1, size, s2, _NORMAL_BLOCK, __FILE__, __LINE__)
    //#define _wdupenv_s(ps1, size, s2) _wdupenv_s_dbg(ps1, size, s2, _NORMAL_BLOCK, __FILE__, __LINE__)

    #if !__STDC__

    #ifdef strdup
    #undef strdup
    #endif
    #define strdup(s) MemoryAllocateTracker::GetInstance().re_strdup_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__)

    #ifdef wcsdup
    #undef wcsdup
    #endif
    #define wcsdup(s) MemoryAllocateTracker::GetInstance().re_wcsdup_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__)

    #ifdef tempnam
    #undef tempnam
    #endif
    #define tempnam(s1, s2) MemoryAllocateTracker::GetInstance().re_tempnam_dbg(s1, s2, _NORMAL_BLOCK, __FILE__, __LINE__)

    //#ifdef getcwd
    //#undef getcwd
    //#endif
    //#define getcwd(s, le) MemoryAllocateTracker::GetInstance().re_getcwd_dbg(s, le, _NORMAL_BLOCK, __FILE__, __LINE__)
    #endif

    #endif

    MemoryAllocateTracker.h

    #pragma once

    #ifdef MEMORY_ALLOC_TRACKER
    #define MEMORY_ALLOC_TRACKER_CLASS _declspec(dllexport)
    #define MEMORY_ALLOC_TRACKER_FUNC _declspec(dllexport)
    #else
    #define MEMORY_ALLOC_TRACKER_CLASS _declspec(dllimport)
    #define MEMORY_ALLOC_TRACKER_FUNC _declspec(dllimport)
    #endif


    class MEMORY_ALLOC_TRACKER_CLASS MemoryAllocateTracker
    {
    public:
    enum AllocState
    {
    AS_NOW,
    AS_MIN,
    AS_MAX
    };
    public:
    static MemoryAllocateTracker& GetInstance();

    int GetAllocatedSize(AllocState state) const;

    void Alloc(void* addr, size_t size, const char * file, long line);
    void Dealloc(void * addr);

    void WriteLog(const char * file = "C:\\temp\\MemoryLeakTracker.txt");

    public:
    void re_free_dbg(void * addr,int blockType);

    void * re_malloc_dbg(size_t size, int blockType, const char * file, int line);

    void * re_calloc_dbg(size_t num, size_t size, int blockType, const char * file, int line);

    void * re_realloc_dbg(void * addr, size_t size, int blockType, const char * file, int line);

    char * re_strdup_dbg(
    const char * str,
    int blockType,
    const char * file,
    int line
    );

    wchar_t
    * re_wcsdup_dbg(
    const wchar_t * str,
    int blockType,
    const char * file,
    int line
    );

    char * re_tempnam_dbg(
    const char * dirname,
    const char * filePrefix,
    int blockType,
    const char * file,
    int line
    );

    char * re_getcwd_dbg(
    char * buf,
    int size,
    int blockType,
    const char * file,
    int line
    );

    private:
    MemoryAllocateTracker();
    ~MemoryAllocateTracker();
    };

    MemoryAllocateTracker.pp

    #include <string>
    #include
    <iomanip>
    #include
    <fstream>
    #include
    <map>
    #include
    <set>
    #include
    "MemoryAllocateTracker.h"
    #ifndef _CRTBLD
    #define _CRTBLD
    #include
    <dbgint.h>
    #endif

    #pragma data_seg("SharedData")

    namespace
    {
    long g_TotalAllocCount = 0;
    HANDLE g_hProcHeap
    = 0;

    // TEMPLATE CLASS allocator
    template<class _Ty>
    class SpecAllocator
    {
    // generic allocator for objects of class _Ty
    public:
    typedef typename _Ty value_type;
    typedef value_type _FARQ
    *pointer;
    typedef value_type _FARQ
    & reference;
    typedef
    const value_type _FARQ *const_pointer;
    typedef
    const value_type _FARQ& const_reference;

    typedef _SIZT size_type;
    typedef _PDFT difference_type;

    template
    <class _Other>
    struct rebind
    {
    // convert an allocator<_Ty> to an allocator <_Other>
    typedef SpecAllocator<_Other> other;
    };

    pointer address(reference _Val)
    const
    {
    // return address of mutable _Val
    return (&_Val);
    }

    const_pointer address(const_reference _Val)
    const
    {
    // return address of nonmutable _Val
    return (&_Val);
    }

    SpecAllocator() _THROW0()
    {
    // construct default allocator (do nothing)
    }

    SpecAllocator(
    const SpecAllocator<_Ty>&) _THROW0()
    {
    // construct by copying (do nothing)
    }

    template
    <class _Other>
    SpecAllocator(
    const SpecAllocator<_Other>&) _THROW0()
    {
    // construct from a related allocator (do nothing)
    }

    template
    <class _Other>
    SpecAllocator
    <_Ty>& operator=(const SpecAllocator<_Other>&)
    {
    // assign from a related allocator (do nothing)
    return (*this);
    }

    void deallocate(pointer _Ptr, size_type)
    {
    // deallocate object at _Ptr, ignore size
    //::HeapFree(g_hProcHeap, 0, _Ptr);
    free(_Ptr);
    }

    pointer allocate(size_type _Count)
    {
    // allocate array of _Count elements
    g_TotalAllocCount += _Count;

    // check for integer overflow
    if (_Count <= 0)
    _Count
    = 0;
    else if (((_SIZT)(-1) / _Count) < sizeof (_Ty))
    _THROW_NCEE(std::bad_alloc, NULL);

    //return (pointer)::HeapAlloc(g_hProcHeap, 0, _Count);
    return (pointer)_malloc_dbg(_Count * sizeof (_Ty), 1, __FILE__, __LINE__);
    }

    pointer allocate(size_type _Count,
    const void _FARQ *)
    {
    // allocate array of _Count elements, ignore hint
    return (allocate(_Count));
    }

    void construct(pointer _Ptr, const _Ty& _Val)
    {
    // construct object at _Ptr with value _Val
    _Construct(_Ptr, _Val);
    }

    void destroy(pointer _Ptr)
    {
    // destroy object at _Ptr
    _Destroy(_Ptr);
    }

    _SIZT max_size()
    const _THROW0()
    {
    // estimate maximum array size
    _SIZT _Count = (_SIZT)(-1) / sizeof (_Ty);
    return (0 < _Count ? _Count : 1);
    }
    };


    //typedef std::basic_string<char, std::char_traits<char>, SpecAllocator<char> > SpecString;
    typedef char * SpecString;
    //typedef std::string SpecString;
    typedef std::set<int, std::less<int>, SpecAllocator<int> > SpecSet;
    struct TrackerNode
    {
    SpecString file;
    long lineNum;
    long allocSize;
    long count;

    long totalCount;
    long leakCount;

    TrackerNode(
    const char * f=0, long l=0, long s=0, long c=1)
    : file(f
    != 0 ? f : "(No file path!)"), lineNum(l),allocSize(s), count(c), totalCount(1), leakCount(0)
    {
    }
    TrackerNode(
    const TrackerNode & o)
    : file(o.file), lineNum(o.lineNum),allocSize(o.allocSize), count(o.count), totalCount(
    1), leakCount(0)
    {
    }
    ~TrackerNode()
    {
    }

    static void * operator new(size_t size)
    {
    return _malloc_dbg(size, 1, __FILE__, __LINE__);
    //return ::HeapAlloc(g_hProcHeap, 0, size);
    }
    static void operator delete(void * ptr)
    {
    //::HeapFree(g_hProcHeap, 0, ptr);
    free(ptr);
    }
    };
    //todo: It should be changed it to shared ptr later.
    typedef TrackerNode * TrackerNodePtr;
    typedef
    const TrackerNode * TrackerNodeConstPtr;

    inline
    bool operator < (const TrackerNode& lt, const TrackerNode& rh)
    {
    if (lt.lineNum < rh.lineNum)
    {
    return true;
    }
    else if (lt.lineNum == rh.lineNum
    && lt.file < rh.file)
    {
    return true;
    }
    else if(lt.lineNum == rh.lineNum
    && lt.file == rh.file
    && lt.allocSize < rh.allocSize)
    {
    return true;
    }
    return false;
    }

    template
    <class _Ty = TrackerNode>
    struct LessForSort:
    public std::binary_function<_Ty, _Ty, bool>
    {
    bool operator() (const _Ty& lt, const _Ty& rh) const
    {
    return lt.allocSize * lt.count > rh.allocSize * rh.count;
    }
    };
    }

    template
    <>
    struct std::less<TrackerNodePtr>:
    public std::binary_function<TrackerNodePtr, TrackerNodePtr, bool>
    {
    bool operator() (const TrackerNodePtr& lt, const TrackerNodePtr& rh) const
    {
    if (lt->lineNum < rh->lineNum)
    {
    return true;
    }
    else if (lt->lineNum == rh->lineNum
    && lt->file < rh->file)
    {
    return true;
    }
    else if(lt->lineNum == rh->lineNum
    && lt->file == rh->file
    && lt->allocSize < rh->allocSize)
    {
    return true;
    }
    return false;
    }
    };

    namespace
    {
    struct AddrCountPair
    {
    long count;
    TrackerNodePtr addr;
    AddrCountPair(
    long c = 0, TrackerNodePtr ptr = 0): count(c), addr(ptr)
    {}
    };
    typedef std::map
    <int *
    ,AddrCountPair
    ,std::less
    <int*>
    ,SpecAllocator
    <std::pair<const int *, AddrCountPair> >
    > TrackerPtrMap;
    typedef TrackerPtrMap::iterator TrackerPtrMapItr;

    typedef std::
    set<TrackerNodePtr
    ,std::less
    <TrackerNodePtr>
    ,SpecAllocator
    <TrackerNodePtr>
    > TrackerPtrSet;
    typedef TrackerPtrSet::iterator TrackerPtrSetItr;

    typedef std::
    set<TrackerNode
    ,std::less
    <TrackerNode>
    ,SpecAllocator
    <TrackerNode>
    > TrackerSet;
    typedef TrackerSet::iterator TrackerSetItr;

    typedef std::
    set<TrackerNode
    ,LessForSort
    <>
    ,SpecAllocator
    <TrackerNode>
    > TrackerSortedSet;
    typedef TrackerSortedSet::iterator TrackerSortedSetItr;

    long g_totalAlloc = 0;
    TrackerPtrMap g_allocMap;
    TrackerPtrSet g_allocSet;

    CMemoryState g_mfcMemStateBegin, g_mfcMemStateEnd;
    }


    namespace
    {
    class Mutex
    {
    friend
    class Lock;
    public:
    Mutex () { InitializeCriticalSection (
    & _critSection); }
    ~Mutex () { DeleteCriticalSection (& _critSection); }
    private:
    void Acquire ()
    {
    EnterCriticalSection (
    & _critSection);
    }
    void Release ()
    {
    LeaveCriticalSection (
    & _critSection);
    }
    private:
    CRITICAL_SECTION _critSection;
    };

    Mutex _mutex;
    class Lock
    {
    public:
    // Acquire the state of the semaphore
    Lock ()
    {
    _mutex.Acquire();
    }
    // Release the state of the semaphore
    ~Lock ()
    {
    _mutex.Release();
    }
    };
    }

    //see bellow...
    MemoryAllocateTracker::MemoryAllocateTracker()
    {
    if (g_hProcHeap == 0)
    {
    //g_hProcHeap = ::HeapCreate(HEAP_CREATE_ENABLE_EXECUTE, 0, 0);
    }
    g_mfcMemStateBegin.Checkpoint();
    }

    MemoryAllocateTracker::
    ~MemoryAllocateTracker()
    {
    Lock threadlock;
    WriteLog();
    if (g_hProcHeap != 0)
    {
    //::HeapDestroy(g_hProcHeap);
    g_hProcHeap = 0;
    }
    }

    int MemoryAllocateTracker::GetAllocatedSize(AllocState state) const
    {
    return 0;
    }

    void MemoryAllocateTracker::Alloc(void* addr, size_t size, const char * file, long line)
    {
    Lock threadlock;

    g_totalAlloc
    += size;
    TrackerNode node(file, line, size,
    1) ;
    TrackerPtrSetItr it
    = g_allocSet.find(&node);
    if (it != g_allocSet.end())
    {
    (
    *it)->count++;
    (
    *it)->totalCount++;
    g_allocMap[(
    int *)addr] = AddrCountPair((*it)->totalCount, (*it));
    }
    else
    {
    TrackerNodePtr nodeptr
    = new TrackerNode(node);

    g_allocSet.insert(nodeptr);
    g_allocMap[(
    int *)addr] = AddrCountPair(nodeptr->totalCount, nodeptr);
    }
    }

    void MemoryAllocateTracker::Dealloc(void* addr)
    {
    Lock threadlock;

    TrackerPtrMapItr it
    = g_allocMap.find((int *)addr);
    if (it != g_allocMap.end())
    {
    g_totalAlloc
    -= it->second.addr->allocSize;
    --(it->second.addr->count);
    g_allocMap.erase(it);
    g_TotalAllocCount
    --;
    }
    }

    MemoryAllocateTracker
    & MemoryAllocateTracker::GetInstance()
    {
    static MemoryAllocateTracker tracker;
    return tracker;
    }

    void MemoryAllocateTracker::WriteLog(const char * file)
    {
    double totalSizeAllocatedBySelf = double(g_TotalAllocCount)/1024;
    if (true)
    {
    std::ofstream
    out("C:\\temp\\_MemoryLeakTracker.txt");
    if (out.fail())
    {
    return;
    }
    out<< std::setw(24)
    << std::setprecision(3)
    << "\t Total Size Allocated by MemoryAllocateTracker.dll:\t "<< totalSizeAllocatedBySelf << " kb \n" << std::endl
    << "\t Total Size of Memory Leak(without MFC):\t " << double(g_totalAlloc)/1024 << " kb \n" << std::endl
    << "\t Size(bytes) \t Count(times) \t Total(kb) \t First Leak Count \t Line number \t file location\n\n";
    for (TrackerPtrMapItr it = g_allocMap.begin(); it != g_allocMap.end(); ++it)
    {
    AddrCountPair
    & pair = it->second;
    if (pair.addr->leakCount <= 0 || pair.count < pair.addr->leakCount)
    {
    pair.addr
    ->leakCount = pair.count;
    }
    }

    for (TrackerPtrSetItr it = g_allocSet.begin(); it != g_allocSet.end();)
    {
    TrackerNodePtr ptr
    = *it;
    if (ptr->count > 0)
    {
    out<< " \t " << ptr->allocSize
    << " \t\t " << ptr->count
    << " \t\t " << double(ptr->count * ptr->allocSize) / 1024
    << " \t\t " << ptr->leakCount
    << " \t\t " << ptr->lineNum
    << " \t\t " << ptr->file
    << std::endl;
    }
    it
    = g_allocSet.erase(it);

    //Do not use free(ptr), else memory of (*ptr)->file is not released.
    delete ptr;
    }
    g_allocMap.clear();
    out.flush();
    out.close();
    }
    g_mfcMemStateEnd.Checkpoint();

    TrackerSet trackerSet ;

    _CrtMemBlockHeader
    * ptr = g_mfcMemStateEnd.m_memState.pBlockHeader;

    long mfcLeakSize = 0;
    while(ptr && ptr != g_mfcMemStateBegin.m_memState.pBlockHeader)
    {
    TrackerNode node(ptr
    ->szFileName, ptr->nLine, ptr->nDataSize, 1);
    mfcLeakSize
    += ptr->nDataSize;

    TrackerSetItr it
    = trackerSet.find(node);
    if (it != trackerSet.end())
    {
    it
    ->count++;
    }
    else
    {
    trackerSet.insert(node);
    }
    ptr
    = ptr->pBlockHeaderNext;
    }

    std::ofstream mfcOut(file);
    mfcOut
    << std::setw(16)
    << std::setprecision(3);

    mfcOut
    << "\t Total Size Allocated by MemoryAllocateTracker.dll:\t "<< totalSizeAllocatedBySelf << " kb \n" << std::endl
    << "\n\t Total Size of Memory Leak:\t " << double(mfcLeakSize)/1024 << " kb\n"<< std::endl
    << "\t Size(bytes) \t Count(times) \t Total(kb) \t Line number \t file location" << std::endl;


    const bool needChecked = false;
    if (needChecked && ptr)
    {
    _CrtMemBlockHeader
    * xptr = ptr;
    _CrtMemBlockHeader
    * rexptr = g_mfcMemStateBegin.m_memState.pBlockHeader;
    size_t count
    = 0;
    while (xptr || rexptr)
    {
    if (xptr != rexptr || ++count > 1000)
    {
    mfcOut
    << "Got Stupid !" << std::endl;
    break;
    }
    xptr
    = xptr ? xptr->pBlockHeaderNext : xptr;
    rexptr
    = rexptr ? rexptr->pBlockHeaderNext : rexptr;
    }
    }

    TrackerSortedSet sortedSet(trackerSet.begin(), trackerSet.end());

    for (TrackerSortedSetItr it = sortedSet.begin(); it != sortedSet.end(); ++it)
    {
    mfcOut
    << " \t " << it->allocSize
    << " \t\t " << it->count
    << " \t\t " << double(it->allocSize * it->count)/1024
    << " \t\t " << it->lineNum
    << " \t\t " << it->file
    << std::endl;
    }

    mfcOut
    << "\n\n\t========================================== "
    << "File Order ==========================================\n\n";
    for (TrackerSetItr it = trackerSet.begin(); it != trackerSet.end(); ++it)
    {
    mfcOut
    << " \t " << it->allocSize
    << " \t\t " << it->count
    << " \t\t " << double(it->allocSize * it->count)/1024
    << " \t\t " << it->lineNum
    << " \t\t " << it->file
    << std::endl;
    }

    mfcOut.flush();
    mfcOut.close();
    }

    void MemoryAllocateTracker::re_free_dbg(void * addr,int blockType)
    {
    _free_dbg(addr, blockType);
    Dealloc(addr);
    }

    void * MemoryAllocateTracker::re_malloc_dbg(size_t size, int blockType, const char * file, int line)
    {
    void * addr = _malloc_dbg(size, blockType, file, line);
    Alloc(addr, size, file, line);
    return addr;
    }

    void * MemoryAllocateTracker::re_calloc_dbg(size_t num, size_t size, int blockType, const char * file, int line)
    {
    void * addr = _calloc_dbg(num, size, blockType, file, line);
    Alloc(addr, num
    * size, file, line);
    return addr;
    }

    void * MemoryAllocateTracker::re_realloc_dbg(void * addr, size_t size, int blockType, const char * file, int line)
    {
    addr
    = _realloc_dbg(addr, size, blockType, file, line);
    Alloc(addr, size, file, line);
    return addr;
    }

    char * MemoryAllocateTracker::re_strdup_dbg(
    const char * str,
    int blockType,
    const char * file,
    int line
    )
    {
    char * addr = _strdup_dbg(str, blockType, file, line);
    Alloc(addr, strlen(addr), file, line);
    return addr;
    }

    wchar_t
    * MemoryAllocateTracker::re_wcsdup_dbg(
    const wchar_t * str,
    int blockType,
    const char * file,
    int line
    )
    {
    wchar_t
    * addr = _wcsdup_dbg(str, blockType, file, line);
    Alloc(addr, wcslen(addr), file, line);
    return addr;
    }

    char * MemoryAllocateTracker::re_tempnam_dbg(
    const char * dirname,
    const char * filePrefix,
    int blockType,
    const char * file,
    int line
    )
    {
    char * addr = _tempnam_dbg(dirname, filePrefix, blockType, file, line);
    Alloc(addr,
    123, file, line);
    return addr;
    }

    char * MemoryAllocateTracker::re_getcwd_dbg(
    char * buf,
    int size,
    int blockType,
    const char * file,
    int line
    )
    {
    char * addr = _getcwd_dbg(buf, size, blockType, file, line);
    Alloc(addr,
    123, file, line);
    return addr;
    }

     
    #pragma data_seg()
    #pragma comment(linker,"/section:SharedData,rws")
      

    For MFC memory check, please refer to Detecting memory leaks: by using CRT diagnostic functions - Part1

    and Inside CRT: Debug Heap Management

    To figure out the function call stack, you need to use dbhelp API within the source above under windows NT.

    Or else, Visual Leak Detector is also a good choice, also see http://vld.codeplex.com/.

  • 相关阅读:
    屏幕截图 从安卓模拟器中识别出屏幕文字
    srcset
    Bitwise and Bit Shift Operators 位运算 取反 补码
    text recognizer (OCR) Engine 光学字符识别
    删除目录下 某类名字的文件
    appmaptile
    登录框
    将代码设置的剪切板内容通过输入法软件粘贴入app搜索框
    面向问题的高级语言
    使用心理视觉来进行图像处理
  • 原文地址:https://www.cnblogs.com/sunkang/p/2052020.html
Copyright © 2011-2022 走看看