First, let's talk about the implementation idea: we can implement a trace class. When operator new is called, we will add the pointer to the allocated memory, the current file, the current row, and other information to the trace member map container, delete this information when you call operator Delete. Defines a global trace object. When the program ends and the object is parsed, it determines whether the MAP member has information. If so, it is printed, indicating that memory leakage has occurred, the output shows which file is allocated with memory but not released.
Debugnew. h:
C ++ code
1 2 3 4 5 6 7 8 9 |
|
# Ifndef _ debug_new_h _ # DEFINE _ debug_new_h _# Ifndef ndebug # Include "tracer. H" # Define new (_ file __, _ line __) # Endif // ndebug
# Endif/_ debug_new_h _ |
Trace. h:
C ++ code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
|
# Ifndef _ tracer_h _ # DEFINE _ tracer_h _# Include <map> # Ifndef ndebug Void * operator new (size_t size, const char * file, long line ); Void operator Delete (void * P ); Void * operator new [] (size_t size, const char * file, long line ); Void operator Delete [] (void * P ); Class Tracer { PRIVATE: Class entry { Public: Entry (const char * file = 0, long line = 0) : File _ (file), line _ (line ){} Const char * file () const { Return file _; } Long Line () const { Return line _; } PRIVATE: Const char * file _; Long Line _; }; Public: Tracer (); ~ Tracer (); Static bool ready; Void add (void * P, const char * file, long line ); Void remove (void * P ); Void dump (); PRIVATE: STD: Map <void *, entry> mapentry _; }; # Endif // ndebug
# Endif // _ tracer_h _ |
Trace. cpp:
C ++ code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
|
# Include <iostream> # Include "tracer. H"# Ifndef ndebug Bool tracer: Ready = false; Tracer: tracer () { Ready = true; } Tracer ::~ Tracer () { Ready = false; Dump (); } Void tracer: add (void * P, const char * file, long line) { Mapentry _ [p] = entry (file, line ); } Void tracer: Remove (void * P) { STD: Map <void *, entry >:: iterator it; It = mapentry _. Find (P ); If (it! = Mapentry _. End ()) { Mapentry _. Erase (it ); } } Void tracer: dump () { If (mapentry _. Size ()> 0) { STD: cout <"*** Memory Leak (s):" <STD: Endl; STD: Map <void *, entry >:: iterator it; For (IT = mapentry _. Begin (); it! = Mapentry _. End (); ++ it) { Const char * file = it-> second. File (); Long line = it-> second. Line (); Int ADDR = reinterpret_cast <int> (IT-> first ); STD: cout <"0x" <STD: Hex <ADDR <":" <File <", line" <STD: Dec <line <STD: Endl; } STD: cout <STD: Endl; } } Tracer newtrace; Void * operator new (size_t size, const char * file, long line) { Void * P = malloc (size ); If (tracer: Ready) { Newtrace. Add (p, file, line ); } Return P; } Void operator Delete (void * P) { If (tracer: Ready) { Newtrace. Remove (P ); } Free (P ); } Void * operator new [] (size_t size, const char * file, long line) { Void * P = malloc (size ); If (tracer: Ready) { Newtrace. Add (p, file, line ); } Return P; } Void operator Delete [] (void * P) { If (tracer: Ready) { Newtrace. Remove (P ); } Free (P ); } # Endif // # ifndef ndebug |
Main. cpp:
C ++ code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
# Include <iostream> Using namespace STD;# Include "debugnew. H" Int main (void) { Int * P = new int; /* Delete P ;*/ Int * P2 = new int [5]; /* Delete [] P2 ;*/ Return 0; } |
Program # define new (_ file __,_ _ line __);
To use the _ file __, and _ line _ macros to represent the file name and number of rows respectively. Reload
Operator new and operator new [] functions and corresponding Delete functions. For more details, see here. When the Global Object newtrace
Call the dump member during structure analysis.
Function. If new and delete do not match, the map will leak information and print it out.
In addition, the memory leakage is tracked only in the debug version (ndebug is not defined), so the # ifndef ndebug
...
# Endif
Generally, the C ++ library does not contain # define new (_ file __, _ line __);
That is, the call is still the original new, but this type is not reloaded in the program.
Because the new and delete functions cannot track memory leaks such as map containers, normally using C ++ library containers will not cause memory leaks,
The C ++ library has been fully implemented, at least much better than the program we write.
Refer:
C ++ primer version 4
Valid tive C ++ 3rd
C ++ programming specifications