Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

370 lines
7.3 KiB

  1. // Copyright (c) 1997-1999 Microsoft Corporation
  2. //
  3. // memory management stuff
  4. //
  5. // 7-30-98 sburns
  6. namespace Burnslib
  7. {
  8. namespace Heap
  9. {
  10. // cause calls to new to capture the call stack at the point of
  11. // allocation.
  12. const WORD TRACE_ALLOCATIONS = (1 << 6);
  13. void
  14. DumpMemoryLeaks();
  15. // called by the InitializationGuard. Read flags from registry,
  16. // sets heap options.
  17. void
  18. Initialize();
  19. // our replacement operator new implementation
  20. void*
  21. OperatorNew(size_t size, const char* file, int line)
  22. throw (std::bad_alloc);
  23. // ... and the corresponding replacement operator delete
  24. // implementation
  25. void
  26. OperatorDelete(void* ptr)
  27. throw ();
  28. } // namespace Heap
  29. } // namespace Burnslib
  30. // Replace the global new and delete operators.
  31. //
  32. // If the allocation fails, the user is given a system modal retry/cancel
  33. // window. If the user opts for retry, re-attempt the allocation. Otherwise
  34. // throw bad_alloc.
  35. //
  36. // Note that the CRT heap APIs are used, and that the debug heap APIs are
  37. // also available. This implies that other modules linking to the same CRT
  38. // dll can install hooks that may break our implementation!
  39. //lint -e(1727) ok that our re-definition is inline
  40. inline
  41. void* __cdecl
  42. operator new(size_t size)
  43. throw (std::bad_alloc)
  44. {
  45. return Burnslib::Heap::OperatorNew(size, 0, 0);
  46. }
  47. //lint -e(1548) ok that our redefinition throw spec doesn't match the CRT
  48. inline
  49. void* __cdecl
  50. operator new[](size_t size)
  51. throw (std::bad_alloc)
  52. {
  53. return Burnslib::Heap::OperatorNew(size, 0, 0);
  54. }
  55. // placement versions of operator new. Although we use the placement syntax,
  56. // we use the additional parameters to record debug information about the
  57. // allocation, rather than indicating a location to allocate memory.
  58. inline
  59. void* __cdecl
  60. operator new(size_t size, const char* file, int line)
  61. throw (std::bad_alloc)
  62. {
  63. return Burnslib::Heap::OperatorNew(size, file, line);
  64. }
  65. inline
  66. void* __cdecl
  67. operator new[](size_t size, const char* file, int line)
  68. throw (std::bad_alloc)
  69. {
  70. return Burnslib::Heap::OperatorNew(size, file, line);
  71. }
  72. inline
  73. void __cdecl
  74. operator delete(void* ptr)
  75. throw ()
  76. {
  77. // check for 0, since deleting the null pointer is legal.
  78. if (ptr)
  79. {
  80. Burnslib::Heap::OperatorDelete(ptr);
  81. }
  82. }
  83. inline
  84. void __cdecl
  85. operator delete[](void* ptr)
  86. throw ()
  87. {
  88. if (ptr)
  89. {
  90. Burnslib::Heap::OperatorDelete(ptr);
  91. }
  92. }
  93. // placement versions of operator delete. We must provide placement versions
  94. // of operator delete with corresponding signatures to the placement versions
  95. // of operator new that we have declared, even though we don't use those
  96. // parameters.
  97. inline
  98. void __cdecl
  99. operator delete(void* ptr, const char*, int)
  100. throw ()
  101. {
  102. if (ptr)
  103. {
  104. Burnslib::Heap::OperatorDelete(ptr);
  105. }
  106. }
  107. inline
  108. void __cdecl
  109. operator delete[](void* ptr, const char*, int)
  110. throw ()
  111. {
  112. if (ptr)
  113. {
  114. Burnslib::Heap::OperatorDelete(ptr);
  115. }
  116. }
  117. namespace Burnslib
  118. {
  119. namespace Heap
  120. {
  121. // An STL-compatible allocator class that uses our replacement new
  122. // and delete operators. We define this class after redefining our
  123. // operator new and delete, above, so that it uses our redefinition.
  124. // @@ (is that necessary, as construct uses placement new?)
  125. template <class T>
  126. class Allocator
  127. {
  128. public:
  129. typedef size_t size_type;
  130. typedef ptrdiff_t difference_type;
  131. typedef T* pointer;
  132. typedef const T* const_pointer;
  133. typedef T& reference;
  134. typedef const T& const_reference;
  135. typedef T value_type;
  136. pointer
  137. address(reference x) const
  138. {
  139. return &x;
  140. }
  141. const_pointer
  142. address(const_reference x) const
  143. {
  144. return &x;
  145. }
  146. // allocate enough storage for n elements of type T
  147. pointer
  148. allocate(size_type n, const void * /* hint */ )
  149. {
  150. size_t size = n * sizeof(T);
  151. return
  152. reinterpret_cast<pointer>(
  153. Burnslib::Heap::OperatorNew(size, 0, 0));
  154. }
  155. void
  156. deallocate(void* p, size_type /* n */ )
  157. {
  158. if (p)
  159. {
  160. Burnslib::Heap::OperatorDelete(p);
  161. }
  162. }
  163. void
  164. construct(pointer p, const T& val)
  165. {
  166. // this calls placement new, which just insures that T's copy ctor
  167. // is executed on memory at address p (so that the p becomes the
  168. // this pointer of the new instance.
  169. //lint -e534 -e522 ignore the return value, which is just p.
  170. new (reinterpret_cast<void*>(p)) T(val);
  171. }
  172. void
  173. destroy(pointer p)
  174. {
  175. ASSERT(p);
  176. (p)->~T();
  177. }
  178. size_type
  179. max_size() const
  180. {
  181. return size_t (-1) / sizeof (T);
  182. }
  183. char*
  184. _Charalloc(size_type n)
  185. {
  186. size_t size = n * sizeof(char*);
  187. return reinterpret_cast<char*>(
  188. Burnslib::Heap::OperatorNew(size, 0, 0));
  189. }
  190. // use default ctor, op=, copy ctor, which do nothing, as this class
  191. // has no members.
  192. };
  193. template<class T, class U>
  194. inline
  195. bool
  196. operator==(
  197. const Burnslib::Heap::Allocator<T>&,
  198. const Burnslib::Heap::Allocator<U>&)
  199. {
  200. return (true);
  201. }
  202. template<class T, class U>
  203. inline
  204. bool
  205. operator!=(
  206. const Burnslib::Heap::Allocator<T>&,
  207. const Burnslib::Heap::Allocator<U>&)
  208. {
  209. return (false);
  210. }
  211. } // namespace Heap
  212. } // namespace Burnslib
  213. #ifdef DBG
  214. // redefine new to call our version that offers file and line number
  215. // tracking. This causes calls to new of the form:
  216. // X* px = new X;
  217. // to expand to:
  218. // X* px = new (__FILE__, __LINE__) X;
  219. // which calls operator new(size_t, const char*, int)
  220. #define new new(__FILE__, __LINE__)
  221. #endif
  222. // You should pass -D_DEBUG to the compiler to get this extra heap
  223. // checking behavior. (The correct way to do this is to set DEBUG_CRTS=1
  224. // in your build environment)
  225. #ifdef _DEBUG
  226. // A HeapFrame is an object that, upon destruction, dumps to the debugger a
  227. // snapshot of the heap allocations that were made since its construction.
  228. // This only works on chk builds. HeapFrame instances may overlap. Place
  229. // one at the beginning of a lexical scope, and you will get a dump of all
  230. // the allocations made in that scope.
  231. //
  232. // See HEAP_FRAME.
  233. namespace Burnslib
  234. {
  235. namespace Heap
  236. {
  237. class Frame
  238. {
  239. public:
  240. // Constructs a new instance. The object will track all allocations
  241. // made after this ctor executes.
  242. //
  243. // file - name of the source file to be dumped with the allocation
  244. // report. ** This pointer is aliased, so it should point to a
  245. // static address. **
  246. //
  247. // line - line number in the above source file to be dumped with the
  248. // allocation report.
  249. Frame(const wchar_t* file, unsigned line);
  250. // Dumps the allocations made since construction.
  251. ~Frame();
  252. private:
  253. const wchar_t* file;
  254. unsigned line;
  255. _CrtMemState checkpoint;
  256. };
  257. }
  258. }
  259. #define HEAP_FRAME() Burnslib::Heap::Frame __frame(__FILE__, __LINE__)
  260. #else
  261. #define HEAP_FRAME()
  262. #endif