00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <math.h>
00004 #include <string.h>
00005 #include <assert.h>
00006 #include <pthread.h>
00007 #include <xassert.h>
00008 #include <xmem.h>
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 #ifdef XMEM_MEMORY_LEAK_LOCATE
00056 static int xmem_memory_leak_locate = 1;
00057 #else
00058 static int xmem_memory_leak_locate = 0;
00059 #endif
00060 #ifdef XMEM_TRAP_ALLOCATION_TIMESTAMP
00061 static int xmem_trap_allocation_timestamp = 1;
00062 #else
00063 static int xmem_trap_allocation_timestamp = 0;
00064 #endif
00065 #ifdef XMEM_REPLACE_LIBC
00066 static int xmem_replace_libc = 1;
00067 #else
00068 static int xmem_replace_libc = 0;
00069 #endif
00070 #ifdef XMEM_HANG_ON_OUM
00071 static int xmem_hang_on_oum = 1;
00072 #else
00073 static int xmem_hang_on_oum = 0;
00074 #endif
00075 #ifdef XMEM_REPORT_LENGTH
00076 static int xmem_report_length = XMEM_REPORT_LENGTH;
00077 #else
00078 static int xmem_report_length = 100;
00079 #endif
00080 #ifdef XMEM_FILL_WITH_NAN
00081 static int xmem_fill_with_nan = 1;
00082 #else
00083 static int xmem_fill_with_nan = 0;
00084 #endif
00085 #ifdef XMEM_ASSERT_ON_NULL_FREE
00086 static int xmem_assert_on_null_free = 1;
00087 #else
00088 static int xmem_assert_on_null_free = 0;
00089 #endif
00090 #ifdef XMEM_WARN_ONLY
00091 static int xmem_warn_only = 1;
00092 #else
00093 static int xmem_warn_only = 0;
00094 #endif
00095
00096 #define ASSERT(val) {if ( xmem_warn_only && !(val)) \
00097 fprintf(stderr, "%s, line %d: Assertion \"" \
00098 #val "\" failed.\n", __FILE__, __LINE__); \
00099 else \
00100 assert_or_hang((val)); }
00101
00102 extern void *__libc_malloc(size_t size);
00103 extern void *__libc_calloc(size_t nmemb, size_t size);
00104 extern void __libc_free(void *ptr);
00105 extern void *__libc_realloc(void *ptr, size_t size);
00106 extern void *__libc_strdup(const char *str);
00107
00108
00109
00110
00112
00113
00114 pthread_mutex_t xmem_mutex = PTHREAD_MUTEX_INITIALIZER;
00115 static char * xmem_timestamp_str = (char *) -1;
00116 static unsigned int xmem_allocation_timestamp = 0;
00117 static size_t xmem_allocation_highwater = 0;
00118
00119 static size_t xmem_allocation_total = 0;
00120
00121
00122
00123
00124
00125 typedef unsigned long guard_word_t;
00126
00127 struct xmem_chunk {
00128 struct xmem_chunk * next;
00129 struct xmem_chunk * prev;
00130 size_t n_bytes;
00131 const char * filename;
00132
00133
00134
00135 int linenum;
00136 unsigned int timestamp;
00137
00138
00139 };
00140
00141 #define XMEM_HASH_SIZE 9973
00142 #define XMEM_HASH_MIN 16
00143 struct xmem_hash_struct
00144 {
00145 unsigned int maxcount[XMEM_HASH_SIZE];
00146 unsigned int count[XMEM_HASH_SIZE];
00147 void **pointers[XMEM_HASH_SIZE];
00148 } xmem_hash;
00149
00150 static int xmem_hash_init = 0;
00151
00152 static void xmem_hash_insert(void *ptr)
00153 {
00154 unsigned int i,hash, newmax;
00155
00156 pthread_mutex_lock( &xmem_mutex );
00157
00158 if (xmem_hash_init == 0)
00159 {
00160 for (i=0;i<XMEM_HASH_SIZE;i++)
00161 {
00162 xmem_hash.pointers[i] = __libc_malloc(XMEM_HASH_MIN*sizeof(void *));
00163 xmem_hash.count[i] = 0;
00164 xmem_hash.maxcount[i] = XMEM_HASH_MIN;
00165 }
00166 xmem_hash_init = 1;
00167 }
00168
00169
00170 hash = ((unsigned long) ptr) % XMEM_HASH_SIZE;
00171 if ( xmem_hash.count[hash]+1 > xmem_hash.maxcount[hash] )
00172 {
00173 newmax = 2*xmem_hash.maxcount[hash];
00174 xmem_hash.pointers[hash] = (void **)__libc_realloc(xmem_hash.pointers[hash],
00175 newmax*sizeof(void *));
00176 xmem_hash.maxcount[hash] = newmax;
00177 }
00178 xmem_hash.pointers[hash][xmem_hash.count[hash]] = ptr;
00179 (xmem_hash.count[hash])++;
00180
00181 pthread_mutex_unlock( &xmem_mutex );
00182 }
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197 static int xmem_hash_remove(void *ptr)
00198 {
00199 unsigned int i;
00200 unsigned long hash;
00201
00202 pthread_mutex_lock( &xmem_mutex );
00203
00204 hash = ((unsigned long) ptr) % XMEM_HASH_SIZE;
00205 for (i=0; i<xmem_hash.count[hash]; i++)
00206 {
00207 if (xmem_hash.pointers[hash][i]==ptr)
00208 {
00209 for (; i<xmem_hash.count[hash]-1; i++)
00210 xmem_hash.pointers[hash][i] = xmem_hash.pointers[hash][i+1];
00211 (xmem_hash.count[hash])--;
00212 pthread_mutex_unlock( &xmem_mutex );
00213 return 1;
00214 }
00215 }
00216 pthread_mutex_unlock( &xmem_mutex );
00217 return 0;
00218 }
00219
00220
00221 #define ALIGNMENT 8 // Return memory blocks aligned on 8-byte
00222
00223
00224
00225 static const size_t xmem_chunk_size = (sizeof (struct xmem_chunk) + sizeof(guard_word_t) +ALIGNMENT-1) & ~(ALIGNMENT-1);
00226
00227
00228
00229 static const guard_word_t guard_word_contents = 0xdeadbeef;
00230
00231
00232
00233 static struct xmem_chunk xmem_header = { &xmem_header, &xmem_header, 0, 0, 0, 0};
00234
00235
00236 static int xmem_alloccount = 0;
00237
00238
00239
00240
00241 #if __BYTE_ORDER == __BIG_ENDIAN
00242 static unsigned char xmem_nan_value[8] = {0x7f,0xf7,0xff,0xff,0x7f,0xbf,0xff,0xff};
00243 #else
00244 static unsigned char xmem_nan_value[8] = {0xff,0xff,0xbf,0x7f,0xff,0xff,0xf7,0x7f};
00245 #endif
00246
00247
00248
00249
00250
00251
00252 void xmem_reset(void)
00253 {
00254 pthread_mutex_lock( &xmem_mutex );
00255 xmem_header.next = &xmem_header;
00256 xmem_header.prev = &xmem_header;
00257 xmem_header.n_bytes = 0;
00258 xmem_header.filename = 0;
00259 xmem_header.linenum = 0;
00260 xmem_header.timestamp = 0;
00261 pthread_mutex_unlock( &xmem_mutex );
00262 }
00263
00264 void xmem_config(int memory_leak_locate, int trap_on_allocation, int replace_libc,
00265 int hang_on_out_of_mem, int report_length, int fill_with_nan,
00266 int assert_on_null_free, int warn_only)
00267 {
00268 pthread_mutex_lock( &xmem_mutex );
00269 xmem_memory_leak_locate = memory_leak_locate;
00270 xmem_trap_allocation_timestamp = trap_on_allocation;
00271 xmem_replace_libc = replace_libc;
00272 xmem_hang_on_oum = hang_on_out_of_mem;
00273 xmem_report_length = report_length;
00274 xmem_fill_with_nan = fill_with_nan;
00275 xmem_assert_on_null_free = assert_on_null_free;
00276 xmem_warn_only = warn_only;
00277 pthread_mutex_unlock( &xmem_mutex );
00278 }
00279
00280
00281 void* xmem_domalloc_params(unsigned int size, const char *filename, int linenum)
00282 {
00283 if (!xmem_memory_leak_locate)
00284 {
00285 void *ptr = (void *)__libc_malloc(size);
00286 if (ptr==NULL)
00287 {
00288 fprintf(stderr,"XMEM: Malloc returned NULL. Probably out of memory. Aborting.\n");
00289 if (xmem_hang_on_oum)
00290 {
00291 hang(HANG_HOURS);
00292 }
00293 else
00294 abort();
00295 }
00296 ++xmem_alloccount;
00297 if (xmem_fill_with_nan)
00298 {
00299 unsigned char *p1= (unsigned char *) ptr, *p2=xmem_nan_value;
00300 while (p1 < (unsigned char *)ptr+size)
00301 {
00302 if (p2 >= xmem_nan_value+8 )
00303 p2 = xmem_nan_value;
00304 *p1++ = *p2++;
00305 }
00306 }
00307 xmem_hash_insert(ptr);
00308 return ptr;
00309 }
00310 else
00311 {
00312 void * user_mem, *ending_guard_word, *starting_guard_word;
00313 unsigned int bad_timestamp;
00314 struct xmem_chunk * mem_chunk;
00315
00316
00317 size_t actual_size = (size + sizeof(guard_word_t)-1) & ~(sizeof (guard_word_t)-1);
00318 size_t request_size = xmem_chunk_size +
00319 + actual_size
00320 + sizeof (guard_word_t);
00321
00322
00323 if (xmem_trap_allocation_timestamp)
00324 {
00325 pthread_mutex_lock( &xmem_mutex );
00326 if ( xmem_timestamp_str == (char *) -1)
00327 {
00328 xmem_timestamp_str = getenv("XMEM_TRAP_ALLOCATION_TIMESTAMP");
00329 }
00330 if ( xmem_timestamp_str )
00331 {
00332 bad_timestamp = (unsigned int) atoi(xmem_timestamp_str);
00333 if (xmem_allocation_timestamp == bad_timestamp)
00334 pthread_mutex_unlock( &xmem_mutex );
00335 ASSERT(xmem_allocation_timestamp != bad_timestamp);
00336 }
00337 pthread_mutex_unlock( &xmem_mutex );
00338 }
00339
00340
00341 mem_chunk = (struct xmem_chunk *)__libc_malloc(request_size);
00342 if (mem_chunk == NULL)
00343 {
00344 xmem_leakcheck();
00345 fprintf(stderr,"XMEM: Malloc returned NULL. Probably out of memory. Aborting.\n");
00346 if (xmem_hang_on_oum)
00347 {
00348 hang(HANG_HOURS);
00349 }
00350 else
00351 abort();
00352 }
00353 mem_chunk->n_bytes = size;
00354 mem_chunk->filename = filename;
00355 mem_chunk->linenum = linenum;
00356 mem_chunk->timestamp = xmem_allocation_timestamp++;
00357 user_mem = (char *)mem_chunk + xmem_chunk_size;
00358 starting_guard_word =(char *)user_mem - sizeof(guard_word_t);
00359 ending_guard_word = (char *)user_mem + actual_size;
00360 *(guard_word_t *)starting_guard_word = guard_word_contents;
00361 *(guard_word_t *)ending_guard_word = guard_word_contents;
00362
00363
00364
00365
00366 pthread_mutex_lock( &xmem_mutex );
00367 mem_chunk->prev = &xmem_header;
00368 mem_chunk->next = xmem_header.next;
00369 mem_chunk->next->prev = mem_chunk;
00370 xmem_header.next = mem_chunk;
00371
00372
00373 xmem_allocation_total += size;
00374 if (xmem_allocation_total > xmem_allocation_highwater)
00375 xmem_allocation_highwater = xmem_allocation_total;
00376 pthread_mutex_unlock( &xmem_mutex );
00377
00378 if (xmem_fill_with_nan)
00379 {
00380 unsigned char *p1= (unsigned char *) user_mem, *p2=xmem_nan_value;
00381 while (p1 < (unsigned char *)user_mem+size)
00382 {
00383 if (p2 >= xmem_nan_value+8 )
00384 p2 = xmem_nan_value;
00385 *p1++ = *p2++;
00386 }
00387 }
00388
00389 xmem_hash_insert(user_mem);
00390 return user_mem;
00391 }
00392 }
00393
00394
00395 char *xmem_strdup_params(const char *str, const char *filename, int linenum)
00396 {
00397 char *result;
00398 int len;
00399 len = strlen(str);
00400 result = xmem_domalloc_params(len+1, filename, linenum);
00401 memcpy(result,str,len+1);
00402 return result;
00403 }
00404
00405
00406
00407
00408 void *
00409 xmem_calloc_params(size_t n_elements, size_t size,
00410 const char * filename, int linenum)
00411 {
00412 void * mem = xmem_domalloc_params(n_elements*size, filename, linenum);
00413 memset(mem, 0, n_elements*size);
00414 return mem;
00415 }
00416
00417
00418
00419
00420
00421 void xmem_dofree(void* ptr)
00422 {
00423 if ( xmem_assert_on_null_free )
00424 {
00425 ASSERT(ptr);
00426 }
00427 else if (ptr == 0)
00428 return;
00429
00430 if (!xmem_memory_leak_locate)
00431 {
00432 if ( xmem_hash_remove(ptr) )
00433 {
00434 pthread_mutex_lock( &xmem_mutex );
00435 --xmem_alloccount;
00436 pthread_mutex_unlock( &xmem_mutex );
00437 }
00438 __libc_free(ptr);
00439 }
00440 else
00441 {
00442 if ( xmem_hash_remove(ptr) )
00443 {
00444 int gc;
00445 struct xmem_chunk * mem_chunk = (struct xmem_chunk *)
00446 ((char *)ptr - xmem_chunk_size);
00447
00448
00449 gc = xmem_check_guardword(ptr);
00450 if (gc==1)
00451 fprintf(stderr,"Starting ");
00452 else if (gc==2)
00453 fprintf(stderr,"Ending ");
00454 else if (gc==3)
00455 fprintf(stderr,"Starting and ending");
00456
00457 if (gc)
00458 {
00459 fprintf(stderr," guardword corrupted in chunk of %ld bytes at %#lx, "
00460 "allocated at %s:%d (timestamp %d)\n",
00461 (unsigned long) mem_chunk->n_bytes,
00462 (unsigned long)((char *)mem_chunk + xmem_chunk_size),
00463 mem_chunk->filename,
00464 mem_chunk->linenum, mem_chunk->timestamp);
00465 printf("To find out where an unfreed chunk was allocated. "
00466 "Do\n setenv XMEM_TRAP_ALLOCATION_TIMESTAMP <timestamp>\n"
00467 "where <timestamp> is one of the values given above and "
00468 "re-run the code.\n");
00469 hang(HANG_HOURS);
00470 }
00471
00472 pthread_mutex_lock( &xmem_mutex );
00473 xmem_allocation_total -= mem_chunk->n_bytes;
00474 mem_chunk->next->prev = mem_chunk->prev;
00475 mem_chunk->prev->next = mem_chunk->next;
00476 pthread_mutex_unlock( &xmem_mutex );
00477
00478 __libc_free(mem_chunk);
00479 }
00480 else
00481 {
00482 __libc_free(ptr);
00483 }
00484 }
00485 }
00486
00487
00488 int xmem_check_guardword(void *ptr)
00489 {
00490 int res=0;
00491 struct xmem_chunk * mem_chunk = (struct xmem_chunk *)
00492 ((char *)ptr - xmem_chunk_size);
00493 size_t actual_size = (mem_chunk->n_bytes + sizeof (guard_word_t)-1) &
00494 ~(sizeof (guard_word_t)-1);
00495
00496
00497 void * ending_guard_word = (char *)ptr + actual_size;
00498 void * starting_guard_word = (char *)ptr-sizeof(guard_word_t);
00499
00500 if (*((guard_word_t *)starting_guard_word) != guard_word_contents)
00501 res = 1;
00502 if (*((guard_word_t *)ending_guard_word) != guard_word_contents)
00503 res += 2;
00504 return res;
00505 }
00506
00507
00508
00509
00510
00511
00512 void* xmem_dorealloc_params(void* ptr, unsigned int size, const char *filename, int linenum)
00513 {
00514 if (!xmem_memory_leak_locate)
00515 {
00516 if (ptr == NULL)
00517 return xmem_domalloc_params(size, filename, linenum);
00518 else
00519 {
00520 xmem_hash_remove(ptr);
00521 ptr = (void *)__libc_realloc(ptr, size);
00522 xmem_hash_insert(ptr);
00523 if (ptr == NULL)
00524 {
00525 fprintf(stderr,"XMEM: Realloc returned NULL. Probably out of memory. Aborting.\n");
00526 if (xmem_hang_on_oum)
00527 hang(HANG_HOURS);
00528 else
00529 abort();
00530 }
00531 return ptr;
00532 }
00533 }
00534 else
00535 {
00536 if (ptr == 0)
00537 return xmem_domalloc_params(size, filename, linenum);
00538 else
00539 {
00540 void * user_mem, * ending_guard_word;
00541
00542 struct xmem_chunk * mem_chunk = (struct xmem_chunk *)
00543 ((char *)ptr - xmem_chunk_size);
00544
00545
00546
00547 size_t actual_size = (size + sizeof(guard_word_t)-1) &
00548 ~(sizeof (guard_word_t)-1);
00549
00550 size_t request_size = xmem_chunk_size +
00551 + actual_size
00552 + sizeof (guard_word_t);
00553
00554 pthread_mutex_lock( &xmem_mutex );
00555 mem_chunk->prev->next = mem_chunk->next;
00556 mem_chunk->next->prev = mem_chunk->prev;
00557
00558
00559 xmem_allocation_total -= mem_chunk->n_bytes;
00560 pthread_mutex_unlock( &xmem_mutex );
00561
00562
00563 mem_chunk = (struct xmem_chunk *)__libc_realloc(mem_chunk, request_size);
00564 if (mem_chunk == NULL)
00565 {
00566
00567
00568 xmem_leakcheck();
00569 fprintf(stderr,"XMEM: Realloc returned NULL. Probably out of memory. Aborting.\n");
00570 if (xmem_hang_on_oum)
00571 {
00572 hang(HANG_HOURS);
00573 }
00574 else
00575 abort();
00576 }
00577 pthread_mutex_lock( &xmem_mutex );
00578 mem_chunk->prev = &xmem_header;
00579 mem_chunk->next = xmem_header.next;
00580 mem_chunk->next->prev = mem_chunk;
00581 xmem_header.next = mem_chunk;
00582 xmem_allocation_total += size;
00583 if (xmem_allocation_total > xmem_allocation_highwater)
00584 xmem_allocation_highwater = xmem_allocation_total;
00585 pthread_mutex_unlock( &xmem_mutex );
00586
00587
00588
00589
00590
00591 mem_chunk->n_bytes = size;
00592 user_mem = (char *)mem_chunk + xmem_chunk_size;
00593
00594 ending_guard_word = (char *)user_mem + actual_size;
00595
00596 *(guard_word_t *)ending_guard_word = guard_word_contents;
00597
00598
00599 xmem_hash_remove(ptr);
00600 xmem_hash_remove(user_mem);
00601 return user_mem;
00602 }
00603 }
00604 }
00605
00606
00607
00608
00609
00610 void xmem_leakreport(void)
00611 {
00612 if (!xmem_memory_leak_locate)
00613 {
00614 fprintf(stderr, "XMEM: Number of unfreed memory buffers is %d.\n", xmem_alloccount);
00615 }
00616 else
00617 {
00618 fprintf(stderr, "XMEM: Largest amount of memory allocated was %lu.\n",
00619 (unsigned long) xmem_allocation_highwater);
00620 fprintf(stderr,"XMEM: Total amount of unfreed memory is %lu.\n",
00621 (unsigned long) xmem_usage(stdout, xmem_report_length));
00622 }
00623 }
00624
00625
00626 int xmem_leakcheck(void)
00627 {
00628 if (!xmem_memory_leak_locate)
00629 {
00630 fprintf(stderr, "XMEM: Number of unfreed memory buffers is %d.\n", xmem_alloccount);
00631 return (xmem_alloccount == 0);
00632 }
00633 else
00634 {
00635 fprintf(stderr, "XMEM: Largest amount of memory allocated was %lu.\n",
00636 (unsigned long) xmem_allocation_highwater);
00637 fprintf(stderr,"XMEM: Total amount of unfreed memory is %lu.\n",
00638 (unsigned long) xmem_usage(stdout, xmem_report_length));
00639 return (xmem_header.next == &xmem_header);
00640 }
00641 }
00642
00643
00644
00645
00646
00647
00654 size_t xmem_recenthighwater()
00655 {
00656 if (xmem_memory_leak_locate)
00657 {
00658 size_t recent_highwater;
00659
00660 pthread_mutex_lock( &xmem_mutex );
00661 recent_highwater = xmem_allocation_highwater;
00662
00663 xmem_allocation_highwater = xmem_allocation_total;
00664
00665 pthread_mutex_unlock( &xmem_mutex );
00666 return recent_highwater;
00667 }
00668 else
00669 return 0;
00670 }
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681 size_t xmem_usage(FILE * fp, int maxlines)
00682 {
00683 size_t unfreed = 0;
00684 if ( xmem_memory_leak_locate )
00685 {
00686 int numlines = 0;
00687 struct xmem_chunk * mem_chunk;
00688
00689 if (xmem_header.next != &xmem_header)
00690 {
00691 if (fp)
00692 fprintf(fp, "XMEM: Unfreed memory:\n");
00693
00694 pthread_mutex_lock( &xmem_mutex );
00695 for (mem_chunk = xmem_header.next;
00696 mem_chunk != &xmem_header;
00697 mem_chunk = mem_chunk->next, numlines++)
00698 {
00699 unfreed += mem_chunk->n_bytes;
00700 if (fp)
00701 {
00702 if ( numlines < maxlines )
00703 fprintf(fp, "%ld bytes at %#lx, allocated at %s:%d "
00704 "(timestamp %d)\n", (unsigned long) mem_chunk->n_bytes,
00705 (unsigned long)((char *)mem_chunk + xmem_chunk_size),
00706 mem_chunk->filename,
00707 mem_chunk->linenum, mem_chunk->timestamp);
00708 else if ( numlines == maxlines )
00709 fprintf(fp,". . .\nXMEM: List truncated. More than %d memory "
00710 "blocks were not freed.\n",
00711 maxlines);
00712 }
00713 }
00714 pthread_mutex_unlock( &xmem_mutex );
00715 printf("To find out where an unfreed chunk was allocated. "
00716 "Do\n setenv XMEM_TRAP_ALLOCATION_TIMESTAMP <timestamp>\n"
00717 "where <timestamp> is one of the values given above and "
00718 "re-run the code.\n");
00719 }
00720 }
00721 return unfreed;
00722 }
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733 int xmem_check_all_guardwords(FILE * fp, int maxlines)
00734 {
00735 int corrupted = 0;
00736 char *ptr;
00737 struct xmem_chunk * mem_chunk;
00738
00739 if (fp==NULL)
00740 return -1;
00741
00742 pthread_mutex_lock( &xmem_mutex );
00743 if ( xmem_memory_leak_locate && (xmem_header.next != &xmem_header))
00744 {
00745
00746 for (mem_chunk = xmem_header.next;
00747 mem_chunk != &xmem_header;
00748 mem_chunk = mem_chunk->next)
00749 {
00750 if ( corrupted < maxlines )
00751 {
00752 ptr = ((char *)mem_chunk + xmem_chunk_size);
00753 if (xmem_check_guardword(ptr))
00754 {
00755 if (corrupted==0)
00756 fprintf(fp, "XMEM: Corrupted memory:\n");
00757 fprintf(fp, "Corrupted block of %ld bytes at %#lx, "
00758 "allocated at %s:%d (timestamp %d)\n",
00759 (unsigned long) mem_chunk->n_bytes,
00760 (unsigned long) ptr,
00761 mem_chunk->filename,
00762 mem_chunk->linenum, mem_chunk->timestamp);
00763 corrupted++;
00764 }
00765 }
00766 else
00767 {
00768 fprintf(fp,". . .\nXMEM: List truncated. More than %d memory "
00769 "blocks were corrupted.\n", maxlines);
00770 break;
00771 }
00772 }
00773 if (corrupted>0)
00774 fprintf(fp,"To find out where a corrupted chunk was allocated. "
00775 "Do\n setenv XMEM_TRAP_ALLOCATION_TIMESTAMP <timestamp>\n"
00776 "where <timestamp> is one of the values given above and "
00777 "re-run the code.\n");
00778 }
00779 pthread_mutex_unlock( &xmem_mutex );
00780 return corrupted;
00781 }
00782
00783
00784
00785
00786
00787 #ifdef XMEM_REPLACE_LIBC
00788
00789 extern void *__real_malloc(size_t size);
00790 extern void *__real_calloc(size_t nmemb, size_t size);
00791 extern void __real_free(void *ptr);
00792 extern void *__real_realloc(void *ptr, size_t size);
00793 extern void *__real_strdup(const char *str);
00794
00795 void *__wrap_malloc(size_t size)
00796 {
00797 if (xmem_replace_libc)
00798 return xmem_domalloc_params(size, __FILE__, __LINE__);
00799 else
00800 return __real_malloc(size);
00801 }
00802
00803 void *__wrap_calloc(size_t n_elements, size_t size)
00804 {
00805 if (xmem_replace_libc)
00806 return xmem_calloc_params(n_elements, size, __FILE__, __LINE__);
00807 else
00808 return __real_calloc(n_elements, size);
00809 }
00810
00811 void __wrap_free(void *ptr)
00812 {
00813 if (xmem_replace_libc)
00814 xmem_dofree(ptr);
00815 else
00816 __real_free(ptr);
00817 }
00818
00819 void *__wrap_realloc(void *ptr, size_t size)
00820 {
00821 if (xmem_replace_libc)
00822 return xmem_dorealloc_params(ptr, size, __FILE__, __LINE__);
00823 else
00824 return __real_realloc(ptr, size);
00825 }
00826
00827
00828 char *__wrap_strdup(const char *str)
00829 {
00830 if (xmem_replace_libc)
00831 return xmem_strdup_params(str, __FILE__, __LINE__);
00832 else
00833 return __real_strdup(str);
00834 }
00835
00836
00837 #endif