libcm is a C development framework with an emphasis on audio signal processing applications.
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

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