8 #ifdef CHECK_MEMORY_LEAKS
60 #if !_FAST_MUTEX_CHECK_INITIALIZATION && !defined(_NOTHREADS)
61 #error "_FAST_MUTEX_CHECK_INITIALIZATION not set: check_leaks may not work"
70 #ifndef _DEBUG_NEW_ALIGNMENT
71 #define _DEBUG_NEW_ALIGNMENT 16
81 #ifndef _DEBUG_NEW_CALLER_ADDRESS
83 #define _DEBUG_NEW_CALLER_ADDRESS __builtin_return_address(0)
85 #define _DEBUG_NEW_CALLER_ADDRESS NULL
98 #ifndef _DEBUG_NEW_ERROR_ACTION
99 #ifndef _DEBUG_NEW_ERROR_CRASH
100 #define _DEBUG_NEW_ERROR_ACTION abort()
102 #define _DEBUG_NEW_ERROR_ACTION do { *((char*)0) = 0; abort(); } while (0)
118 #ifndef _DEBUG_NEW_FILENAME_LEN
120 #define _DEBUG_NEW_FILENAME_LEN 0
122 #define _DEBUG_NEW_FILENAME_LEN 44
138 #ifndef _DEBUG_NEW_PROGNAME
139 #define _DEBUG_NEW_PROGNAME NULL
149 #ifndef _DEBUG_NEW_STD_OPER_NEW
150 #define _DEBUG_NEW_STD_OPER_NEW 1
160 #ifndef _DEBUG_NEW_TAILCHECK
161 #define _DEBUG_NEW_TAILCHECK 0
169 #ifndef _DEBUG_NEW_TAILCHECK_CHAR
170 #define _DEBUG_NEW_TAILCHECK_CHAR 0xCC
181 #ifndef _DEBUG_NEW_USE_ADDR2LINE
183 #define _DEBUG_NEW_USE_ADDR2LINE 1
185 #define _DEBUG_NEW_USE_ADDR2LINE 0
190 #pragma warning(disable: 4074) // #pragma init_seg(compiler) used
191 #pragma warning(disable: 4290) // C++ exception specification ignored
192 #if _MSC_VER >= 1400 // Visual Studio 2005 or later
193 #pragma warning(disable: 4996) // Use the `unsafe' strncpy
195 #pragma init_seg(compiler)
198 #undef _DEBUG_NEW_EMULATE_MALLOC
199 #undef _DEBUG_NEW_REDEFINE_NEW
204 #define _DEBUG_NEW_REDEFINE_NEW 0
211 (((s) + _DEBUG_NEW_ALIGNMENT - 1) & ~(_DEBUG_NEW_ALIGNMENT - 1))
221 const size_t PLATFORM_MEM_ALIGNMENT =
sizeof(size_t) * 2;
226 struct new_ptr_list_t
228 new_ptr_list_t* next;
229 new_ptr_list_t* prev;
233 #if _DEBUG_NEW_FILENAME_LEN == 0
236 char file[_DEBUG_NEW_FILENAME_LEN];
248 const unsigned MAGIC = 0x4442474E;
253 const int ALIGNED_LIST_ITEM_SIZE = ALIGN(
sizeof(new_ptr_list_t));
258 static new_ptr_list_t new_ptr_list = {
263 #if _DEBUG_NEW_FILENAME_LEN == 0
287 static size_t total_mem_alloc = 0;
317 #if _DEBUG_NEW_USE_ADDR2LINE
327 static bool print_position_from_addr(
const void* addr)
329 static const void* last_addr = NULL;
330 static char last_info[256] =
"";
331 if (addr == last_addr)
333 if (last_info[0] ==
'\0')
335 fprintf(new_output_fp,
"%s", last_info);
340 const char addr2line_cmd[] =
"addr2line -e ";
341 #if defined(__CYGWIN__) || defined(_WIN32)
342 const int exeext_len = 4;
344 const int exeext_len = 0;
346 #if !defined(__CYGWIN__) && defined(__unix__)
347 const char ignore_err[] =
" 2>/dev/null";
348 #elif defined(__CYGWIN__) || \
349 (defined(_WIN32) && defined(WINVER) && WINVER >= 0x0500)
350 const char ignore_err[] =
" 2>nul";
352 const char ignore_err[] =
"";
354 char* cmd = (
char*)alloca(strlen(new_progname)
356 +
sizeof addr2line_cmd - 1
357 +
sizeof ignore_err - 1
360 strcpy(cmd, addr2line_cmd);
361 strcpy(cmd +
sizeof addr2line_cmd - 1, new_progname);
362 size_t len = strlen(cmd);
363 #if defined(__CYGWIN__) || defined(_WIN32)
365 || (strcmp(cmd + len - 4,
".exe") != 0 &&
366 strcmp(cmd + len - 4,
".EXE") != 0))
368 strcpy(cmd + len,
".exe");
372 sprintf(cmd + len,
" %p%s", addr, ignore_err);
373 FILE* fp = popen(cmd,
"r");
376 char buffer[
sizeof last_info] =
"";
378 if (fgets(buffer,
sizeof buffer, fp))
380 len = strlen(buffer);
381 if (buffer[len - 1] ==
'\n')
382 buffer[--len] =
'\0';
384 int res = pclose(fp);
389 if (res == 0 && len > 0)
392 if (buffer[len - 1] ==
'0' && buffer[len - 2] ==
':')
396 fprintf(new_output_fp,
"%s", buffer);
397 strcpy(last_info, buffer);
412 static bool print_position_from_addr(
const void*)
416 #endif // _DEBUG_NEW_USE_ADDR2LINE
429 static void print_position(
const void* ptr,
int line)
433 fprintf(new_output_fp,
"%s:%d", (
const char*)ptr, line);
435 else if (ptr != NULL)
437 if (!print_position_from_addr(ptr))
438 fprintf(new_output_fp,
"%p", ptr);
442 fprintf(new_output_fp,
"<Unknown>");
446 #if _DEBUG_NEW_TAILCHECK
455 static bool check_tail(new_ptr_list_t* ptr)
457 const unsigned char*
const pointer = (
unsigned char*)ptr +
458 ALIGNED_LIST_ITEM_SIZE + ptr->size;
459 for (
int i = 0; i < _DEBUG_NEW_TAILCHECK; ++i)
460 if (pointer[i] != _DEBUG_NEW_TAILCHECK_CHAR)
476 static void* alloc_mem(
size_t size,
const char* file,
int line,
bool is_array)
479 #if _DEBUG_NEW_TYPE == 1
480 STATIC_ASSERT(_DEBUG_NEW_ALIGNMENT >= PLATFORM_MEM_ALIGNMENT,
481 Alignment_too_small);
483 STATIC_ASSERT((_DEBUG_NEW_ALIGNMENT & (_DEBUG_NEW_ALIGNMENT - 1)) == 0,
484 Alignment_must_be_power_of_two);
485 STATIC_ASSERT(_DEBUG_NEW_TAILCHECK >= 0, Invalid_tail_check_length);
486 size_t s = size + ALIGNED_LIST_ITEM_SIZE + _DEBUG_NEW_TAILCHECK;
487 new_ptr_list_t* ptr = (new_ptr_list_t*)malloc(s);
490 #if _DEBUG_NEW_STD_OPER_NEW
494 fprintf(new_output_fp,
495 "Out of memory when allocating %lu bytes\n",
496 (
unsigned long)size);
497 fflush(new_output_fp);
498 _DEBUG_NEW_ERROR_ACTION;
501 void* pointer = (
char*)ptr + ALIGNED_LIST_ITEM_SIZE;
502 #if _DEBUG_NEW_FILENAME_LEN == 0
506 strncpy(ptr->file, file, _DEBUG_NEW_FILENAME_LEN - 1)
507 [_DEBUG_NEW_FILENAME_LEN - 1] =
'\0';
509 ptr->addr = (
void*)file;
512 ptr->is_array = is_array;
517 ptr->prev = new_ptr_list.prev;
518 ptr->next = &new_ptr_list;
519 new_ptr_list.prev->next = ptr;
520 new_ptr_list.prev = ptr;
522 #if _DEBUG_NEW_TAILCHECK
523 memset((
char*)pointer + size, _DEBUG_NEW_TAILCHECK_CHAR,
524 _DEBUG_NEW_TAILCHECK);
526 if (new_verbose_flag)
529 fprintf(new_output_fp,
530 "new%s: allocated %p (size %lu, ",
531 is_array ?
"[]" :
"",
532 pointer, (
unsigned long)size);
534 print_position(ptr->file, ptr->line);
536 print_position(ptr->addr, ptr->line);
537 fprintf(new_output_fp,
")\n");
539 total_mem_alloc += size;
551 static void free_pointer(
void* pointer,
void* addr,
bool is_array)
555 new_ptr_list_t* ptr =
556 (new_ptr_list_t*)((
char*)pointer - ALIGNED_LIST_ITEM_SIZE);
557 if (ptr->magic != MAGIC)
561 fprintf(new_output_fp,
"delete%s: invalid pointer %p (",
562 is_array ?
"[]" :
"", pointer);
563 print_position(addr, 0);
564 fprintf(new_output_fp,
")\n");
567 fflush(new_output_fp);
568 _DEBUG_NEW_ERROR_ACTION;
570 if (is_array != ptr->is_array)
574 msg =
"delete[] after new";
576 msg =
"delete after new[]";
578 fprintf(new_output_fp,
579 "%s: pointer %p (size %lu)\n\tat ",
581 (
char*)ptr + ALIGNED_LIST_ITEM_SIZE,
582 (
unsigned long)ptr->size);
583 print_position(addr, 0);
584 fprintf(new_output_fp,
"\n\toriginally allocated at ");
586 print_position(ptr->file, ptr->line);
588 print_position(ptr->addr, ptr->line);
589 fprintf(new_output_fp,
"\n");
590 fflush(new_output_fp);
591 _DEBUG_NEW_ERROR_ACTION;
593 #if _DEBUG_NEW_TAILCHECK
594 if (!check_tail(ptr))
597 fflush(new_output_fp);
598 _DEBUG_NEW_ERROR_ACTION;
603 total_mem_alloc -= ptr->size;
605 ptr->prev->next = ptr->next;
606 ptr->next->prev = ptr->prev;
608 if (new_verbose_flag)
611 fprintf(new_output_fp,
612 "delete%s: freed %p (size %lu, %lu bytes still allocated)\n",
613 is_array ?
"[]" :
"",
614 (
char*)ptr + ALIGNED_LIST_ITEM_SIZE,
615 (
unsigned long)ptr->size, (
unsigned long)total_mem_alloc);
631 new_ptr_list_t* ptr = new_ptr_list.next;
632 while (ptr != &new_ptr_list)
634 const char*
const pointer = (
char*)ptr + ALIGNED_LIST_ITEM_SIZE;
635 if (ptr->magic != MAGIC)
637 fprintf(new_output_fp,
638 "warning: heap data corrupt near %p\n",
641 #if _DEBUG_NEW_TAILCHECK
642 if (!check_tail(ptr))
644 fprintf(new_output_fp,
645 "warning: overwritten past end of object at %p\n",
649 fprintf(new_output_fp,
650 "Leaked object at %p (size %lu, ",
652 (
unsigned long)ptr->size);
654 print_position(ptr->file, ptr->line);
656 print_position(ptr->addr, ptr->line);
657 fprintf(new_output_fp,
")\n");
661 if (new_verbose_flag || leak_cnt)
662 fprintf(new_output_fp,
"*** %d leaks found\n", leak_cnt);
677 fprintf(new_output_fp,
"*** Checking for memory corruption: START\n");
678 for (new_ptr_list_t* ptr = new_ptr_list.next;
679 ptr != &new_ptr_list;
682 const char*
const pointer = (
char*)ptr + ALIGNED_LIST_ITEM_SIZE;
683 if (ptr->magic == MAGIC
684 #
if _DEBUG_NEW_TAILCHECK
689 #if _DEBUG_NEW_TAILCHECK
690 if (ptr->magic != MAGIC)
693 fprintf(new_output_fp,
694 "Heap data corrupt near %p (size %lu, ",
696 (
unsigned long)ptr->size);
697 #if _DEBUG_NEW_TAILCHECK
701 fprintf(new_output_fp,
702 "Overwritten past end of object at %p (size %lu, ",
704 (
unsigned long)ptr->size);
708 print_position(ptr->file, ptr->line);
710 print_position(ptr->addr, ptr->line);
711 fprintf(new_output_fp,
")\n");
714 fprintf(new_output_fp,
"*** Checking for memory corruption: %d FOUND\n",
734 size_t offset = (
char*)pointer - (
char*)NULL;
735 if (offset % PLATFORM_MEM_ALIGNMENT != 0) {
736 offset -=
sizeof(size_t);
737 if (offset % PLATFORM_MEM_ALIGNMENT != 0) {
740 pointer = (
char*)pointer -
sizeof(
size_t);
743 new_ptr_list_t* ptr =
744 (new_ptr_list_t*)((
char*)pointer - ALIGNED_LIST_ITEM_SIZE);
745 if (ptr->magic != MAGIC || ptr->line != 0)
748 fprintf(new_output_fp,
749 "warning: debug_new used with placement new (%s:%d)\n",
753 if (new_verbose_flag) {
755 fprintf(new_output_fp,
756 "info: pointer %p allocated from %s:%d\n",
759 #if _DEBUG_NEW_FILENAME_LEN == 0
762 strncpy(ptr->file,
_M_file, _DEBUG_NEW_FILENAME_LEN - 1)
763 [_DEBUG_NEW_FILENAME_LEN - 1] =
'\0';
778 void*
operator new(
size_t size,
const char* file,
int line)
780 void* ptr = alloc_mem(size, file, line,
false);
781 #if _DEBUG_NEW_STD_OPER_NEW
785 throw std::bad_alloc();
801 void*
operator new[](
size_t size,
const char* file,
int line)
803 void* ptr = alloc_mem(size, file, line,
true);
804 #if _DEBUG_NEW_STD_OPER_NEW
808 throw std::bad_alloc();
822 void*
operator new(
size_t size)
throw(std::bad_alloc)
824 return operator new(size, (
char*)_DEBUG_NEW_CALLER_ADDRESS, 0);
835 void*
operator new[](
size_t size)
throw(std::bad_alloc)
837 return operator new[](size, (
char*)_DEBUG_NEW_CALLER_ADDRESS, 0);
847 void*
operator new(
size_t size,
const std::nothrow_t&)
throw()
849 return alloc_mem(size, (
char*)_DEBUG_NEW_CALLER_ADDRESS, 0,
false);
859 void*
operator new[](
size_t size,
const std::nothrow_t&)
throw()
861 return alloc_mem(size, (
char*)_DEBUG_NEW_CALLER_ADDRESS, 0,
true);
869 void operator delete(
void* pointer)
throw()
871 free_pointer(pointer, _DEBUG_NEW_CALLER_ADDRESS,
false);
879 void operator delete[](
void* pointer)
throw()
881 free_pointer(pointer, _DEBUG_NEW_CALLER_ADDRESS,
true);
895 void operator delete(
void* pointer,
const char* file,
int line)
throw()
897 if (new_verbose_flag)
900 fprintf(new_output_fp,
901 "info: exception thrown on initializing object at %p (",
903 print_position(file, line);
904 fprintf(new_output_fp,
")\n");
906 operator delete(pointer);
917 void operator delete[](
void* pointer,
const char* file,
int line)
throw()
919 if (new_verbose_flag)
922 fprintf(new_output_fp,
923 "info: exception thrown on initializing objects at %p (",
925 print_position(file, line);
926 fprintf(new_output_fp,
")\n");
928 operator delete[](pointer);
937 void operator delete(
void* pointer,
const std::nothrow_t&)
throw()
939 operator delete(pointer, (
char*)_DEBUG_NEW_CALLER_ADDRESS, 0);
948 void operator delete[](
void* pointer,
const std::nothrow_t&)
throw()
950 operator delete[](pointer, (
char*)_DEBUG_NEW_CALLER_ADDRESS, 0);
972 if (--
_S_count == 0 && new_autocheck_flag)
975 new_verbose_flag =
true;
976 #if defined(__GNUC__) && __GNUC__ >= 3
977 if (!getenv(
"GLIBCPP_FORCE_NEW") && !getenv(
"GLIBCXX_FORCE_NEW"))
978 fprintf(new_output_fp,
979 "*** WARNING: GCC 3 or later is detected, please make sure the\n"
980 " environment variable GLIBCPP_FORCE_NEW (GCC 3.2 and 3.3) or\n"
981 " GLIBCXX_FORCE_NEW (GCC 3.4 and later) is defined. Check the\n"
982 " README file for details.\n");
const char * new_progname
#define STATIC_ASSERT(_Expr, _Msg)
void _M_process(void *pointer)
int check_mem_corruption()