libcm is a C development framework with an emphasis on audio signal processing applications.
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

cmMem.h 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. //( { file_desc: "Implements a memory allocation manager interface." kw:[ base ]}
  2. //
  3. //
  4. // Using cmMem allows memory leaks and some instances of memory corruption
  5. // to be be detected. It can also perform memory block alignment.
  6. //
  7. // The cmMm class acts as an interface for implementing functions designed to replace
  8. // malloc() and free(). cmMm does not actually allocate memory itself but rather
  9. // tracks and conditions block of memory provided by other sources. In this sense
  10. // it acts as a backend for a memory allocation manager.
  11. // cmMallocDebug.h gives an example of using cmMm to interface to malloc() and free().
  12. // cmLinkedHeap.h gives an example of using cmMm to link to an alternate heap manager.
  13. // See cmMdTest() and cmLHeapTest() for usage examples of cmMm.
  14. //
  15. // cmMm works as follows:
  16. //
  17. // 1. A client memory manager creates and configures a cmMm object via cmMmInitialize().
  18. // As part of the configuration the client gives callback functions which implement
  19. // actual memory allocation and release. In practice this means the callback probably
  20. // call malloc() or free().
  21. //
  22. // 2. At some point later when the client needs to allocate a block of memory it calls
  23. // cmMmAllocate() with the size of the requested block. cmMm translates this request
  24. // into a call to the client provided memory allocation callback to get a block of raw
  25. // memory which is slightly larger than the request block.
  26. //
  27. // 3. Given the raw memory block cmMm conditions it in the following ways and returns
  28. // it to the client.
  29. //
  30. // * The base of the blocks data area is shifted such that it is has an arbitrary
  31. // address aligned according to the value set by the alignByteCnt parameter to cmMmInitialize().
  32. // Address aligment is sometimes required by routines which make use of the the SIMD
  33. // unit on some CPUs.
  34. // * 'Guard' bytes are prepended and appended to the blocks data area.
  35. // These bytes are set to the known fixed value (0xaa). At some point later cmMm can
  36. // then test for accidental writes just before or just after the legal data area by
  37. // checking the value of these guard bytes.
  38. // * The number of bytes allocated is written just prior to the leading guard bytes.
  39. // This allows the memory manager to track the
  40. // size of the memory and thereby makes reallocations() to smaller or equal data areas
  41. // very fast. This also allows the size of the data area to be known just by having a
  42. // pointer to the data area (see cmMmByteCount()). This basic information is not availabe
  43. // via malloc().
  44. // * A record is added to an internal database to track the allocation code location
  45. // (file name, file line, function name) and the allocation status (active or released).
  46. // * The client may request that a new block of memory be automatically filled with zeros.
  47. // If automatic zeroing is not requested then the block is filled with 0x55 to indicate that
  48. // it is not initialized. This can be useful when attempting to recognize uninitialized
  49. // memory during debugging.
  50. //
  51. // When a client requests that a block of memory is released cmMm does the following:
  52. //
  53. // 1. If deferred release is enabled (kDeferFreeFl) then the block is filled with 0x33
  54. // but the callback to freeFunc() is not actually made. This allows cmMm to track attempted
  55. // writes to freed memory areas. When deferred release is enabled the freeFunc() is not called
  56. // on any blocks until cmMmFinalize(). If the program continually allocates memory over the
  57. // life of the program this may mean that the program will eventually exhaust physical memory.
  58. //
  59. // 2. If tracking is enabled (kTrackMmFl) then the block pointer is looked up in the internal database.
  60. // If the pointer is not found then a kMissingRecdRC is returned indicating an attempt to release
  61. // a non-allocated block.
  62. //
  63. // 3. If tracking is enabled (kTrackMmFl) then the block is marked as released in the
  64. // internal tracking database. At the end of the program all blocks should be marked for release
  65. // otherwise they are considered leaks.
  66. //
  67. //
  68. // At any time during the life of the cmMm object the client can request a report of the
  69. // allocated blocks cmMmReport(). This report examines each allocated block for corrupt guard bytes,
  70. // double frees (attempts to release an allocated block that was already released), and
  71. // leaked blocks (active blocks).
  72. //
  73. //)
  74. #ifndef cmMem_h
  75. #define cmMem_h
  76. #ifdef __cplusplus
  77. extern "C" {
  78. #endif
  79. //(
  80. typedef cmHandle_t cmMmH_t; //< cmMm handle type.
  81. typedef cmRC_t cmMmRC_t; //< cmMm result code types.
  82. // cmMm result codes
  83. enum
  84. {
  85. kOkMmRC = cmOkRC,
  86. kObjAllocFailMmRC,
  87. kTrkAllocFailMmRC,
  88. kAllocFailMmRC,
  89. kFreeFailMmRC,
  90. kMissingRecdMmRC,
  91. kGuardCorruptMmRC,
  92. kWriteAfterFreeMmRC,
  93. kLeakDetectedMmRC,
  94. kDblFreeDetectedMmRC,
  95. kParamErrMmRC
  96. };
  97. // All cmMmH_t variables should be initialized with this value prior to calling cmMmInitialize().
  98. extern cmMmH_t cmMmNullHandle;
  99. // Function signature for data allocation routine client provided to cmMmInitialize().
  100. // Return NULL if byteCnt == 0.
  101. typedef void* (*cmAllocMmFunc_t)(void* funcArgPtr, unsigned byteCnt);
  102. // Function signature for data release routine client provided to cmMmInitialize().
  103. // Return true on success and false on failure. Return true if ptr==NULL.
  104. typedef bool (*cmFreeMmFunc_t)( void* funcArgPtr, void* ptr);
  105. // Flags for use with cmMmInitialize()
  106. enum
  107. {
  108. kTrackMmFl = 0x01, //< Track alloc's and free's for use by cmMmReport().
  109. kDeferFreeMmFl = 0x02, //< Defer memory release until cmMmFinalize() (ignored unless kTrackMmFl is set.) Allows checks for 'write after release'.
  110. kFillUninitMmFl = 0x04, //< Fill uninitialized (non-zeroed) memory with a 0x55 upon allocation
  111. kFillFreedMmFl = 0x08 //< Fill freed memory with 0x33. This allow checks for wite-after-free.
  112. };
  113. // Create a new cmMm object.
  114. // If *hp was not initalized by an earlier call to cmMmInitialize() then it should
  115. // be set to cmMmNullHandle prior to calling this function. If *hp is a valid handle
  116. // then it is automatically finalized by an internal call to cmMmFinalize() prior to
  117. // being re-iniitalized.
  118. cmMmRC_t cmMmInitialize(
  119. cmMmH_t* hp, //< Pointer to a client provided cmMmH_t handle to recieve the handle of the new object.
  120. cmAllocMmFunc_t allocFunc, //< The memory allocation function equivalent to malloc().
  121. cmFreeMmFunc_t freeFunc, //< The memory release function equivalent to free().
  122. void* funcArgPtr, //< An application supplied data value sent with call backs to allocFunc() and freeFunc().
  123. unsigned guardByteCnt, //< Count of guardBytes to precede and follow each allocated block.
  124. unsigned alignByteCnt, //< Address alignment to provide for each allocated block.
  125. unsigned flags, //< Configuration flags (See cmXXXMmFl).
  126. cmRpt_t* rptPtr //< Pointer to an error reporting object.
  127. );
  128. // Release a cmMm object created by an earlier call to cmMmInitialize(). Upon successful completion *hp is set to cmMmNullHandle.
  129. cmMmRC_t cmMmFinalize( cmMmH_t* hp );
  130. unsigned cmMmGuardByteCount( cmMmH_t h ); //< Return the count of guard bytes this cmMm object is applying.
  131. unsigned cmMmAlignByteCount( cmMmH_t h ); //< Return the byte alignment this cmMm object is applying.
  132. unsigned cmMmInitializeFlags( cmMmH_t h ); //< Return the configuration flags this cmMm object was initialized with.
  133. // Return true if 'h' is a valid handle for an existing cmMm object.
  134. bool cmMmIsValid( cmMmH_t h );
  135. // flags for use with cmMmAllocate()
  136. enum cmMmAllocFlags_t
  137. {
  138. kZeroMmFl = 0x01, //< Initialize new memory area to zero.
  139. kAlignMmFl = 0x02, //< Align the returned memory according to the alignByteCnt set in cmMmInitialize().
  140. kPreserveMmFl = 0x04 //< Preserve existing memory contents during reallocation (orgDataPtr!=NULL).
  141. };
  142. // Allocate a block of memory.
  143. // Calling this function results in a call to the function named in allocFunc() in cmMmInitialize().
  144. void* cmMmAllocate(
  145. cmMmH_t h, //< Handle for this cmMm object returned from an earlier successful call to cmMmInitialize().
  146. void* orgDataPtr, //< If this is a re-allocation then this pointer should point to the original allocation otherwise it should be NULL.
  147. unsigned newEleCnt, //< Count of elmements in this allocation.
  148. unsigned newEleByteCnt, //< Bytes per element in this allocation. The total memory request is newEleCnt*newEleByteCnt.
  149. enum cmMmAllocFlags_t flags, //< See cmMmAllocFlags_t.
  150. const char* fileName, //< Name of the C file from which the allocation request is being made.
  151. const char* funcName, //< Name of the C function from which the allocation request is being made.
  152. unsigned fileLine //< Line in the C file on which the allocation request is being made.
  153. );
  154. // Free memory pointed to by dataPtr.
  155. // If dataPtr==NULL then the functon does nothing and returns.
  156. // Calling this function results in a call to the function named in freeFunc() in cmMmInitialize().
  157. // This is the release mode memory free routine. See cmMmFreeDebug() for the debug mode memory release routine.
  158. // See \ref debug_mode for more about debug vs. release mode.
  159. cmMmRC_t cmMmFree( cmMmH_t h, void* dataPtr );
  160. // Debug mode version of cmMmFree(). See cmMmFree() for the release mode memory free routine.
  161. // See debug_mode for more about debug vs. release mode.
  162. // This routine is functionally identical to the cmMmFree() but takes the calling
  163. // location information for use in tracking the block of memory.
  164. cmMmRC_t cmMmFreeDebug( cmMmH_t h, void* dataPtr, const char* fileName, const char* funcName, unsigned fileLine );
  165. // This function is identical to cmMmFree() but takes the address of the pointer
  166. // to the block of memory to free. Upon successful completion *dataPtrPtr is
  167. // set to NULL. In general this should be the preferred version of the free routine
  168. // because it helps to eliminate problems of reusing deallocated memory blocks.
  169. // Note that although dataPtrPtr must point to a valid address *dataPtrPtr may be NULL.
  170. // This routine is generally only used in the release compile mode.
  171. // See cmMmFreePtrDebug() for the debug mode version. See \ref debug_mode for more
  172. // about compile vs. release mode.
  173. cmMmRC_t cmMmFreePtr( cmMmH_t h, void** dataPtrPtr );
  174. // Debug compile mode version of cmMmFreePtr().
  175. // This function is functionally identical to cmMmFreePtr() but accepts information
  176. // on the location of the call to aid in debuging.
  177. cmMmRC_t cmMmFreePtrDebug( cmMmH_t h, void* dataPtr, const char* fileName, const char* funcName, unsigned fileLine );
  178. // Return the size of a memory block returned from cmMmAllocate().
  179. unsigned cmMmByteCount( cmMmH_t h, const void* dataPtr );
  180. // Return the unique id associated with an address returned from cmMmAllocate().
  181. unsigned cmMmDebugId( cmMmH_t h, const void* dataPtr);
  182. // Flags for use with cmMmReport().
  183. enum
  184. {
  185. kSuppressSummaryMmFl = 0x01, //< Do not print a memory use summary report.
  186. kIgnoreNormalMmFl = 0x02, //< Do not print information for non-leaked,non-corrupt memory blocks.
  187. kIgnoreLeaksMmFl = 0x04 //< Do not print information for leaked blocks.
  188. };
  189. // Report on the memory tracking data.
  190. // Returns kMmOkRC if no errors were found otherwise returns the error of the
  191. // last anomoly reported.
  192. cmMmRC_t cmMmReport( cmMmH_t h, unsigned flags );
  193. // Analyze the memory assoc'd with a specific tracking record for corruption.
  194. // Returns: kOkMmRC,kGuardCorruptMmRC,kWriteAfterFreeMmRc, or kMissingRecdMmRC.
  195. // This function is only useful if kTrackMmFl was set in cmMmInitialize().
  196. // Write-after-free errors are only detectable if kDeferFreeMmFl was set in cmMmInitialize().
  197. cmMmRC_t cmMmIsGuardCorrupt( cmMmH_t h, unsigned id );
  198. // Check all tracking records by calling cmMmmIsGuardCorrupt() on each record.
  199. cmMmRC_t cmMmCheckAllGuards( cmMmH_t h );
  200. //)
  201. #ifdef __cplusplus
  202. }
  203. #endif
  204. #endif