PageRenderTime 415ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/brlcad/branches/bullet/src/other/step/src/base/scl_memmgr.cc

https://bitbucket.org/vrrm/brl-cad-copy-for-fast-history-browsing-in-git
C++ | 410 lines | 274 code | 67 blank | 69 comment | 26 complexity | e79abb1873f160ad229fc4e27409131b MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, LGPL-2.1, Apache-2.0, AGPL-3.0, LGPL-3.0, GPL-3.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, 0BSD, BSD-3-Clause
  1. #define SCL_MEMMGR_CC
  2. #include "scl_memmgr.h"
  3. #if 0
  4. #if __APPLE__
  5. # include <malloc/malloc.h>
  6. #else
  7. # include <malloc.h>
  8. #endif
  9. #else
  10. # include <stdlib.h>
  11. #endif
  12. #include <stdio.h>
  13. #include <string>
  14. #include <set>
  15. #ifdef SCL_MEMMGR_ENABLE_CHECKS
  16. /**
  17. scl_memmgr_error definition
  18. */
  19. class scl_memmgr_error {
  20. private:
  21. std::string _srcfile;
  22. unsigned int _srcline;
  23. unsigned int _occurences;
  24. public:
  25. scl_memmgr_error( const std::string & file, const unsigned int line );
  26. scl_memmgr_error( const scl_memmgr_error & rhs );
  27. ~scl_memmgr_error( void );
  28. bool operator<( const scl_memmgr_error & rhs ) const;
  29. std::string getsrcfile( void ) const;
  30. unsigned int getsrcline( void ) const;
  31. unsigned int getoccurences( void ) const;
  32. };
  33. typedef std::set<scl_memmgr_error> scl_memmgr_errors;
  34. typedef std::set<scl_memmgr_error>::iterator scl_memmgr_error_iterator;
  35. /**
  36. scl_memmgr_record definition
  37. */
  38. class scl_memmgr_record {
  39. private:
  40. void * _addr;
  41. size_t _size;
  42. std::string _srcfile;
  43. unsigned int _srcline;
  44. public:
  45. scl_memmgr_record( void * addr, size_t size, const char * file, const unsigned int line );
  46. scl_memmgr_record( void * addr );
  47. scl_memmgr_record( const scl_memmgr_record & rhs );
  48. ~scl_memmgr_record( void );
  49. bool operator<( const scl_memmgr_record & rhs ) const;
  50. void * getaddr( void ) const;
  51. size_t getsize( void ) const;
  52. std::string getsrcfile( void ) const;
  53. unsigned int getsrcline( void ) const;
  54. };
  55. typedef std::set<scl_memmgr_record> scl_memmgr_records;
  56. typedef std::set<scl_memmgr_record>::iterator scl_memmgr_record_iterator;
  57. #endif /* SCL_MEMMGR_ENABLE_CHECKS */
  58. /**
  59. scl_memmgr definition
  60. */
  61. class scl_memmgr {
  62. private:
  63. #ifdef SCL_MEMMGR_ENABLE_CHECKS
  64. bool _record_insert_busy, _record_erase_busy;
  65. // memory allocation/reallocation records, inserted at allocation, erased at deallocation.
  66. scl_memmgr_records _records;
  67. // memory stats
  68. unsigned int _allocated; // amount of memory allocated simultaniously
  69. unsigned int _maximum_allocated; // maximum amount of memory allocated simultaniously
  70. unsigned int _allocated_total; // total amount of memory allocated in bytes
  71. unsigned int _reallocated_total; // total amount of memory reallocated in bytes
  72. unsigned int _deallocated_total; // total amount of memory deallocated in bytes
  73. #endif /* SCL_MEMMGR_ENABLE_CHECKS */
  74. protected:
  75. public:
  76. scl_memmgr( void );
  77. ~scl_memmgr( void );
  78. void * allocate( size_t size, const char * file, const int line );
  79. void * reallocate( void * addr, size_t size, const char * file, const int line );
  80. void deallocate( void * addr, const char * file, const int line );
  81. };
  82. /**
  83. scl_memmgr instance.
  84. There should be one static instance of memmgr.
  85. This instance is automatically destroyed when application exits, so this allows us to add
  86. memory leak detection in it's destructor.
  87. */
  88. scl_memmgr memmgr;
  89. /**
  90. c memory functions implementation
  91. */
  92. extern "C" {
  93. void * scl_malloc_fn( unsigned int size, const char * file, const int line ) {
  94. return memmgr.allocate( size, file, line );
  95. }
  96. void * scl_calloc_fn( unsigned int count, unsigned int size, const char * file, const int line ) {
  97. return memmgr.allocate( count * size, file, line );
  98. }
  99. void * scl_realloc_fn( void * addr, unsigned int size, const char * file, const int line ) {
  100. return memmgr.reallocate( addr, size, file, line );
  101. }
  102. void scl_free_fn( void * addr ) {
  103. memmgr.deallocate( addr, "", 0 );
  104. }
  105. }
  106. /**
  107. c++ memory operators implementation
  108. */
  109. void * scl_operator_new( size_t size, const char * file, const int line ) {
  110. return memmgr.allocate( size, file, line );
  111. }
  112. void scl_operator_delete( void * addr, const char * file, const int line ) {
  113. memmgr.deallocate( addr, file, line );
  114. }
  115. void scl_operator_delete( void * addr ) {
  116. memmgr.deallocate( addr, "", 0 );
  117. }
  118. /**
  119. scl_memmgr implementation
  120. */
  121. scl_memmgr::scl_memmgr( void ) {
  122. #ifdef SCL_MEMMGR_ENABLE_CHECKS
  123. _record_insert_busy = false;
  124. _record_erase_busy = false;
  125. _allocated = 0;
  126. _maximum_allocated = 0;
  127. _allocated_total = 0;
  128. _reallocated_total = 0;
  129. _deallocated_total = 0;
  130. #endif /* SCL_MEMMGR_ENABLE_CHECKS */
  131. }
  132. /**
  133. Destructor:
  134. scl_memmgr::~scl_memmgr(void)
  135. Description:
  136. The scl_memmgr destructor is used to check for memory leaks when enabled.
  137. All records still present when scl_memmgr instance is destroyed can be considered as
  138. memory leaks.
  139. */
  140. scl_memmgr::~scl_memmgr( void ) {
  141. #ifdef SCL_MEMMGR_ENABLE_CHECKS
  142. scl_memmgr_record_iterator irecord;
  143. scl_memmgr_errors errors;
  144. scl_memmgr_error_iterator ierror;
  145. // Check if total allocated equals total deallocated
  146. if( _allocated_total != _deallocated_total ) {
  147. // todo: generate warning for possible memory leaks, enable full memory leak checking
  148. printf("scl_memmgr warning: Possible memory leaks detected (%d of %d bytes)\n", _allocated_total - _deallocated_total, _allocated_total);
  149. }
  150. // Compact leaks into an error list to prevent same leak being reported multiple times.
  151. _record_insert_busy = true;
  152. _record_erase_busy = true;
  153. for( irecord = _records.begin();
  154. irecord != _records.end();
  155. irecord ++ ) {
  156. scl_memmgr_error error( irecord->getsrcfile(), irecord->getsrcline() );
  157. ierror = errors.find( error );
  158. if( ierror == errors.end() ) {
  159. errors.insert( error );
  160. }
  161. //else
  162. // ierror->occurences ++;
  163. }
  164. _record_insert_busy = false;
  165. _record_erase_busy = false;
  166. // Loop through memory leaks to generate/buffer errors
  167. for( ierror = errors.begin();
  168. ierror != errors.end();
  169. ierror ++ ) {
  170. // todo: generate error for memory leak
  171. printf( "scl_memmgr warning: Possible memory leak in %s line %d\n", ierror->getsrcfile().c_str(), ierror->getsrcline() );
  172. }
  173. // Clear remaining records
  174. _record_erase_busy = true;
  175. _records.clear();
  176. errors.clear();
  177. _record_erase_busy = false;
  178. #endif /* SCL_MEMMGR_ENABLE_CHECKS */
  179. }
  180. void * scl_memmgr::allocate( size_t size, const char * file, const int line ) {
  181. void * addr;
  182. // Allocate
  183. addr = malloc( size );
  184. if( addr == NULL ) {
  185. // todo: error allocation failed
  186. printf( "scl_memmgr error: Memory allocation failed in %s line %d\n", file, line );
  187. }
  188. // Some stl implementations (for example debian gcc) use the new operator to construct
  189. // new elements when inserting scl_memmgr_record. When this our new operator gets used
  190. // for this operation, this would result in an infinite loop. This is fixed by the
  191. // _record_insert_busy flag.
  192. #ifdef SCL_MEMMGR_ENABLE_CHECKS
  193. if( !_record_insert_busy ) {
  194. // Store record for this allocation
  195. _record_insert_busy = true;
  196. _records.insert( scl_memmgr_record( addr, size, file, line ) );
  197. _record_insert_busy = false;
  198. // Update stats
  199. _allocated += size;
  200. if( _allocated > _maximum_allocated ) {
  201. _maximum_allocated = _allocated;
  202. }
  203. _allocated_total += size;
  204. }
  205. #endif /* SCL_MEMMGR_ENABLE_CHECKS */
  206. return addr;
  207. }
  208. void * scl_memmgr::reallocate( void * addr, size_t size, const char * file, const int line ) {
  209. #ifdef SCL_MEMMGR_ENABLE_CHECKS
  210. scl_memmgr_record_iterator record;
  211. if( !_record_insert_busy ) {
  212. // Find record of previous allocation/reallocation
  213. record = _records.find( scl_memmgr_record( addr ) );
  214. if( record == _records.end() ) {
  215. // todo: error reallocating memory not allocated?
  216. printf( "scl_memmgr warning: Reallocation of not allocated memory at %s line %d\n", file, line );
  217. } else {
  218. // Update stats
  219. _allocated -= record->getsize();
  220. _deallocated_total += record->getsize();
  221. // Erase previous allocation/reallocation
  222. _record_erase_busy = true;
  223. _records.erase( record );
  224. _record_erase_busy = false;
  225. }
  226. }
  227. #endif /* SCL_MEMMGR_ENABLE_CHECKS */
  228. // Reallocate
  229. addr = realloc( addr, size );
  230. if( addr == NULL ) {
  231. // todo: error reallocation failed
  232. printf( "scl_memmgr error: Reallocation failed at %s line %d\n", file, line );
  233. }
  234. #ifdef SCL_MEMMGR_ENABLE_CHECKS
  235. if( !_record_insert_busy ) {
  236. // Store record for this reallocation
  237. _record_insert_busy = true;
  238. _records.insert( scl_memmgr_record( addr, size, file, line ) );
  239. _record_insert_busy = false;
  240. // Update stats
  241. _allocated += size;
  242. if( _allocated > _maximum_allocated ) {
  243. _maximum_allocated = _allocated;
  244. }
  245. _allocated_total += size;
  246. _reallocated_total += size;
  247. }
  248. #endif /* SCL_MEMMGR_ENABLE_CHECKS */
  249. return addr;
  250. }
  251. void scl_memmgr::deallocate( void * addr, const char * file, const int line ) {
  252. #ifdef SCL_MEMMGR_ENABLE_CHECKS
  253. scl_memmgr_record_iterator record;
  254. if( !_record_erase_busy ) {
  255. // Find record of previous allocation/reallocation
  256. record = _records.find( scl_memmgr_record( addr ) );
  257. if( record == _records.end() ) {
  258. // todo: error free called for not allocated memory?
  259. printf( "scl_memmgr warning: Deallocate of not allocated memory at %s line %d\n", file, line );
  260. } else {
  261. // Update stats
  262. _allocated -= record->getsize();
  263. _deallocated_total += record->getsize();
  264. // Erase record
  265. _record_erase_busy = true;
  266. _records.erase( record );
  267. _record_erase_busy = false;
  268. }
  269. }
  270. #endif /* SCL_MEMMGR_ENABLE_CHECKS */
  271. // Deallocate
  272. free( addr );
  273. }
  274. #ifdef SCL_MEMMGR_ENABLE_CHECKS
  275. /**
  276. scl_memmgr_error implementation
  277. */
  278. scl_memmgr_error::scl_memmgr_error( const std::string & file, const unsigned int line ) {
  279. _srcfile = file;
  280. _srcline = line;
  281. _occurences = 1;
  282. }
  283. scl_memmgr_error::scl_memmgr_error( const scl_memmgr_error & rhs ) {
  284. _srcfile = rhs._srcfile;
  285. _srcline = rhs._srcline;
  286. _occurences = rhs._occurences;
  287. }
  288. scl_memmgr_error::~scl_memmgr_error( void ) {
  289. }
  290. bool scl_memmgr_error::operator<( const scl_memmgr_error & rhs ) const {
  291. if( _srcfile == rhs._srcfile ) {
  292. return _srcline < rhs._srcline;
  293. }
  294. return _srcfile < rhs._srcfile;
  295. }
  296. std::string scl_memmgr_error::getsrcfile( void ) const {
  297. return _srcfile;
  298. }
  299. unsigned int scl_memmgr_error::getsrcline( void ) const {
  300. return _srcline;
  301. }
  302. unsigned int scl_memmgr_error::getoccurences( void ) const {
  303. return _occurences;
  304. }
  305. /**
  306. scl_memmgr_record implementation
  307. */
  308. scl_memmgr_record::scl_memmgr_record( void * addr, size_t size, const char * file, const unsigned int line ) {
  309. _addr = addr;
  310. _size = size;
  311. _srcfile = file;
  312. _srcline = line;
  313. }
  314. scl_memmgr_record::scl_memmgr_record( void * addr ) {
  315. _addr = addr;
  316. _size = 0;
  317. _srcfile = "";
  318. _srcline = -1;
  319. }
  320. scl_memmgr_record::scl_memmgr_record( const scl_memmgr_record & rhs ) {
  321. _addr = rhs._addr;
  322. _size = rhs._size;
  323. _srcfile = rhs._srcfile;
  324. _srcline = rhs._srcline;
  325. }
  326. scl_memmgr_record::~scl_memmgr_record( void ) {
  327. }
  328. bool scl_memmgr_record::operator<( const scl_memmgr_record & rhs ) const {
  329. return _addr < rhs._addr;
  330. }
  331. void * scl_memmgr_record::getaddr( void ) const {
  332. return _addr;
  333. }
  334. size_t scl_memmgr_record::getsize( void ) const {
  335. return _size;
  336. }
  337. std::string scl_memmgr_record::getsrcfile( void ) const {
  338. return _srcfile;
  339. }
  340. unsigned int scl_memmgr_record::getsrcline( void ) const {
  341. return _srcline;
  342. }
  343. #endif /* SCL_MEMMGR_ENABLE_CHECKS */