• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            春暖花開
            雪化了,花開了,春天來了
            posts - 149,comments - 125,trackbacks - 0
             

            檢測內存泄露的工具:debugnew
            http://dev.csdn.net/article/58/58407.shtm

            網上有一個流傳甚廣的檢測內存泄露的工具:debugnew(debugnew.h/debugnew.cpp)
            用法很簡單,把debugnew.cpp放在項目里一起編譯,需要檢測的文件把debugnew.h嵌在文件的最前面。

            為方便使用,對源代碼做了一些小的改動。

            下面是一些簡單的說明:

            1、new 的重載
            void* operator new (size_t size, const char* file, int line);        ⑴
            void* operator new [] (size_t size, const char*  file, int line);     ?、?/p>

            在需要檢測的文件里,重定義new
            #define new new(__FILE__, __LINE__)

            造成的結果:
            ClassName *p = new ClassName; => ClassName *p = new(__FILE__, __LINE__) ClassName;
            // 實際會調用void* operator new (size_t size, const char* file, int line);

            ClassName **pp = new classname[count]; => ClassName **pp = new(__FILE__, __LINE__) ClassName[count];
            // 實際會調用void* operator new [] (size_t size, const char*  file, int line);

            這其實是利用了placement new的語法,通過一個簡單的宏,就可以把普通的new操作對應到相應的重載( ⑴,⑵ )上去。

            2、delete 的重載
            void operator delete (void* p, const char* file, int line);                   ⑶
            void operator delete [] (void* p, const char* file, int line);                ⑷
            void operator delete (void* p);                                               ⑸
            void operator delete [] (void* p);                                            ⑹

            因為沒有類似于placement new的語法,所以就不能用一個宏來替換替換delete了。要調用帶有更多信息的delete操作符,只能修改源代碼了。
            delete p; => delete ( p, __FILE__, __LINE__ );
            delete []pp; => delete [] ( pp, __FILE__, __LINE__ );
            但這個工作很煩瑣,如果并不需要多余的信息的話,簡單地重載delete( ⑸,⑹ )就可以了。

            3、檢測和統計
            程序開始時,在debugnew.cpp中會創建一個DebugNewTracer對象
            在重載的new操作符( ⑴,⑵ )中,每一次內存分配都會被記錄,而在delete( ⑶,⑷,⑸,⑹ )中則會刪除相應的記錄。
            當程序結束,DebugNewTracer對象被銷毀,它的析構函數會dump剩余的記錄,這就是泄露的內存了。

            在原有代碼的基礎上,增加了記錄size的功能,這樣可以在每次new和delete時,看到實際占用的內存。所有信息可以dump出來,也可以寫入log。


            5、源代碼

            ********************************************************
            debugnew.h:

            /*
             filename: debugnew.h
             
             This code is based on code retrieved from a web site. The
             author was not identified, so thanks go to anonymous.

             This is used to substitute a version of the new operator that
             can be used for debugging memory leaks. To use it:
             
             - In any (all?) code files #include debugnew.h. Make sure all
              system files (i.e. those in <>'s) are #included before
              debugnew.h, and that any header files for your own code
              are #included after debugnew.h. The reason is that some
              system files refer to ::new, and this will not compile
              if debugnew is in effect. You may still have problems
              if any of your own code refers to ::new, or if any
              of your own files #include system files that use ::new
              and which have not already been #included before
              debugnew.h.
             - Add debugnew.cpp to the CodeWarrior project or compile
              it into your Linux executable. If debugnew.cpp is in the
              project, then debugnew.h must be #included in at least
              one source file
            */

            #ifndef __DEBUGNEW_H__
            #define __DEBUGNEW_H__

            #include <map>

            #define LOG_FILE

            #if defined(LOG_FILE)
            #define LOG_FILE_NAME "./debugnew.log"
            #endif

            void* operator new (std::size_t size, const char* file, int line);
            void operator delete (void* p, const char* name, int line);
            void* operator new [] (std::size_t size, const char* file, int line);
            void operator delete [] (void* p, const char* name, int line);

            class DebugNewTracer  {
            private:
             
             class Entry  {
             public:
              Entry (char const* file, int line) : _file (file), _line (line) {}
              Entry (char const* file, int line, int size) : _file (file), _line (line), _size (size) {}
              Entry () : _file (0), _line (0), _size (0) {}
              const char* File () const { return _file; }
              int Line () const { return _line; }
              size_t Size () const { return _size; }
             private:
              char const* _file;
              int _line;
              size_t _size;
             };

             class Lock {
             public:
              Lock (DebugNewTracer & DebugNewTracer) : _DebugNewTracer (DebugNewTracer) {
               _DebugNewTracer.lock ();
              }
              ~Lock () {
               _DebugNewTracer.unlock ();
              }
             private:
              DebugNewTracer & _DebugNewTracer;
             };
             typedef std::map<void*, Entry>::iterator iterator;
             friend class Lock;
             public:
             DebugNewTracer ();
             ~DebugNewTracer ();
             void Add (void* p, const char* file, int line);
             void Add (void* p, const char* file, int line, size_t size);
             void Remove (void* p);
             void Dump ();

             static bool Ready;

             private:
             void lock () { _lockCount++; }
             void unlock () { _lockCount--; }

             private:

             std::map<void*, Entry> _map;
             int _lockCount;
             size_t _totalsize;
            #if defined(LOG_FILE)
             FILE* _logfp;
            #endif
             };

             // The file that implements class DebugNewTracer
             // does NOT want the word "new" expanded.
             // The object DebugNewTrace is defined in that
             // implementation file but only declared in any other file.
            #ifdef DEBUGNEW_CPP
            DebugNewTracer DebugNewTrace;
            #else
            #define new new(__FILE__, __LINE__)
            extern DebugNewTracer DebugNewTrace;
            #endif

            #endif//#ifndef __DEBUGNEW_H__


            ********************************************************
            debugnew.cpp:

            /*
             filename: debugnew.cpp

             This is used to substitute a version of the new operator that
             can be used for debugging memory leaks. In any (all?) code
             files #include debugnew.h. Add debugnew.cpp to the project.
            */

            #include <iostream>
            #include <map>

            using namespace std;

             // This disables macro expansion of "new".
             // This statement should only appear in this file.
            #define DEBUGNEW_CPP

            #include "debugnew.h"

            DebugNewTracer::DebugNewTracer () : _lockCount (0)
            {
              // Once this object is constructed all calls to
              // new should be traced.

             Ready = true;
             _totalsize = 0;
            #if defined(LOG_FILE)
             if( (_logfp=fopen(LOG_FILE_NAME,"wt")) == NULL )
             {
              printf(" Error! file: debugnew.log can not open@!\n");
              return;
             } 
             fprintf(_logfp,"new, delete list:\n");
             fflush(_logfp);
            #endif
             
            }
                    
            void DebugNewTracer::Add (void* p, const char* file, int line)
            {
              // Tracing must not be done a second time
              // while it is already
              // in the middle of executing
             if (_lockCount > 0)
              return;

               // Tracing must be disabled while the map
               // is in use in case it calls new.
             DebugNewTracer::Lock lock (*this);
             _map [p] = Entry (file, line);
            }

            void DebugNewTracer::Add (void* p, const char* file, int line, size_t size)
            {
             // Tracing must not be done a second time
             // while it is already
             // in the middle of executing
             if (_lockCount > 0)
              return;

              // Tracing must be disabled while the map
              // is in use in case it calls new.
             DebugNewTracer::Lock lock (*this);
            #if 1
             //´Óȫ·¾¶ÖÐÌáÈ¡ÎļþÃû
             //linuxϵÄgcc,__FILE__½ö½ö°üÀ¨ÎļþÃû£¬windowsϵÄvc,__FILE__°üÀ¨È«Â·¾¶,ËùÒÔÓÐÕâÑùµÄ´¦Àí
             file = strrchr(file,'\\')== NULL?file:strrchr(file,'\\')+1;
            #endif
             _map [p] = Entry (file, line, size);
             _totalsize += size;
            #if defined(LOG_FILE)
             fprintf(_logfp,"*N p = 0x%08x, size = %6d,  %-22s, Line: %4d.  totalsize =%8d\n", p, size, file, line, _totalsize);
             fflush(_logfp);
            #endif
            }


            void DebugNewTracer::Remove (void* p)
            {
             // Tracing must not be done a second time
             // while it is already
             // in the middle of executing
             if (_lockCount > 0)
              return;

              // Tracing must be disabled while the map
              // is in use in case it calls new.
             DebugNewTracer::Lock lock (*this);

             iterator it = _map.find (p);

             if (it != _map.end ())
             {
              size_t size = (*it).second.Size();
              _totalsize -= size;
            #if defined(LOG_FILE)
              fprintf(_logfp,"#D p = 0x%08x, size = %6u.%39stotalsize =%8d\n", p, size, "-----------------------------------  ", _totalsize );
              fflush(_logfp);
            #endif
              _map.erase (it);
             }
             else
             {
            #if defined(LOG_FILE)
              fprintf(_logfp,"#D p = 0x%08x. error point!!!\n", p );
              fflush(_logfp);
            #endif
             }
            }

            DebugNewTracer::~DebugNewTracer ()
            {
             // Trace must not be called if Dump indirectly
             // invokes new, so it must be disabled before
             // Dump is called. After this destructor executes
             // any other global objects that get destructed
             // should not do any tracing.
             Ready = false;
             Dump ();
            #if defined(LOG_FILE)
             fclose(_logfp);
            #endif
            }

            // If some global object is destructed after DebugNewTracer
            // and if that object calls new, it should not trace that
            // call to new.
            void DebugNewTracer::Dump ()
            {
             if (_map.size () != 0)
             {
              std::cout << _map.size () << " memory leaks detected\n";
            #if defined(LOG_FILE)
              fprintf(_logfp, "\n\n***%d memory leaks detected\n", _map.size ());
              fflush(_logfp);
            #endif
              for (iterator it = _map.begin (); it != _map.end (); ++it)
              {
               char const * file = it->second.File ();
               int line = it->second.Line ();
               int size = it->second.Size ();
               std::cout << file << ", "  << line << std::endl;
            #if defined(LOG_FILE)
               fprintf(_logfp,"%s, %d, size=%d\n", file, line, size);
               fflush(_logfp);
            #endif
              }
             }
             else
             {
              std::cout << "no leaks detected\n";
            #if defined(LOG_FILE)
              fprintf(_logfp,"no leaks detected\n");
              fflush(_logfp);
            #endif
             }

            }

            // If some global object is constructed before DebugNewTracer
            // and if that object calls new, it should not trace that
            // call to new.
            bool DebugNewTracer::Ready = false;

            void* operator new (size_t size, const char* file, int line)
            {
             void * p = malloc (size);
             if (DebugNewTracer::Ready)
              DebugNewTrace.Add (p, file, line, size);
             return p;
            }

            void operator delete (void* p, const char* file, int line)
            {
             file = 0; // avoid a warning about argument not used in function
             line = 0; // avoid a warning about argument not used in function
             
             if (DebugNewTracer::Ready)
              DebugNewTrace.Remove (p);
             free (p);
            }
                    
            void* operator new [] (size_t size, const char*  file, int line)
            {
             void * p = malloc (size);
             if (DebugNewTracer::Ready)
              DebugNewTrace.Add (p, file, line, size);
             return p;
            }

            void operator delete [] (void* p, const char* file, int line)
            {
             file = 0; // avoid a warning about argument not used in function
             line = 0; // avoid a warning about argument not used in function
             
             if (DebugNewTracer::Ready)
               DebugNewTrace.Remove (p);
             free (p);
            }
                    
            void* operator new (size_t size)
            {
             void * p = malloc (size);
             // When uncommented these lines cause entries in the map for calls to new
             // that were not altered to the debugnew version. These are likely calls
             // in library functions and the presence in the dump of these entries
             // is usually misleading.
             // if (DebugNewTracer::Ready)
             //   DebugNewTrace.Add (p, "?", 0);
             return p;
            }
             
            void operator delete (void* p)
            {
             if (DebugNewTracer::Ready)
              DebugNewTrace.Remove (p);
             free (p);
            }

            //add by yugang
            void operator delete [] (void* p)
            {
             if (DebugNewTracer::Ready)
              DebugNewTrace.Remove (p);
             free (p);
            }

            posted on 2008-11-02 10:52 Sandy 閱讀(730) 評論(0)  編輯 收藏 引用 所屬分類: C++
            久久久国产亚洲精品| 久久噜噜电影你懂的| 精品国产一区二区三区久久| 久久天天躁狠狠躁夜夜不卡| 午夜天堂精品久久久久| 精品永久久福利一区二区| 亚洲乱亚洲乱淫久久| 伊人久久大香线蕉成人| 久久国产色AV免费观看| 77777亚洲午夜久久多喷| 国产精品免费看久久久香蕉| 亚洲国产精品成人久久蜜臀| 久久婷婷成人综合色综合| 久久久久亚洲国产| 91久久精一区二区三区大全| 麻豆一区二区99久久久久| 99久久精品国产一区二区三区| 思思久久99热只有频精品66| 久久精品国产亚洲一区二区三区| 中文国产成人精品久久不卡| 日韩欧美亚洲综合久久影院d3| 国内精品人妻无码久久久影院导航| 国产精品成人99久久久久| 99久久精品影院老鸭窝| 久久天天躁夜夜躁狠狠| 久久夜色精品国产| 久久精品无码一区二区三区免费 | 久久99国产精品成人欧美| 久久久久亚洲AV成人片| 久久这里的只有是精品23| 久久国产香蕉一区精品| 久久精品中文字幕第23页| 女人香蕉久久**毛片精品| 久久精品国产影库免费看 | 久久笫一福利免费导航| 精品无码久久久久久久动漫| 国产一级持黄大片99久久| 成人资源影音先锋久久资源网| 亚洲国产精品无码久久| 久久久久久久亚洲Av无码| AV狠狠色丁香婷婷综合久久 |