43 PRAGMA45(GCC diagnostic ignored
"-Wcast-qual")
59 #if NVWA_LINUX || NVWA_APPLE
64 #ifndef WIN32_LEAN_AND_MEAN
65 #define WIN32_LEAN_AND_MEAN
74 #undef _DEBUG_NEW_EMULATE_MALLOC
75 #undef _DEBUG_NEW_REDEFINE_NEW
80 #define _DEBUG_NEW_REDEFINE_NEW 0
83 #if !_FAST_MUTEX_CHECK_INITIALIZATION && !defined(_NOTHREADS)
84 #error "_FAST_MUTEX_CHECK_INITIALIZATION not set: check_leaks may not work"
93 #ifndef _DEBUG_NEW_ALIGNMENT
94 #define _DEBUG_NEW_ALIGNMENT 16
104 #ifndef _DEBUG_NEW_CALLER_ADDRESS
106 #define _DEBUG_NEW_CALLER_ADDRESS __builtin_return_address(0)
108 #define _DEBUG_NEW_CALLER_ADDRESS _NULLPTR
121 #ifndef _DEBUG_NEW_ERROR_ACTION
122 #ifndef _DEBUG_NEW_ERROR_CRASH
123 #define _DEBUG_NEW_ERROR_ACTION abort()
125 #define _DEBUG_NEW_ERROR_ACTION do { *((char*)0) = 0; abort(); } while (0)
142 #ifndef _DEBUG_NEW_FILENAME_LEN
144 #define _DEBUG_NEW_FILENAME_LEN 0
146 #define _DEBUG_NEW_FILENAME_LEN 44
162 #ifndef _DEBUG_NEW_PROGNAME
163 #define _DEBUG_NEW_PROGNAME _NULLPTR
179 #ifndef _DEBUG_NEW_REMEMBER_STACK_TRACE
180 #define _DEBUG_NEW_REMEMBER_STACK_TRACE 0
190 #ifndef _DEBUG_NEW_STD_OPER_NEW
191 #define _DEBUG_NEW_STD_OPER_NEW 1
201 #ifndef _DEBUG_NEW_TAILCHECK
202 #define _DEBUG_NEW_TAILCHECK 0
222 #ifndef _DEBUG_NEW_USE_ADDR2LINE
224 #define _DEBUG_NEW_USE_ADDR2LINE 1
226 #define _DEBUG_NEW_USE_ADDR2LINE 0
231 #pragma warning(disable: 4074)
232 #pragma warning(disable: 4290)
234 #pragma warning(disable: 4996)
236 #pragma init_seg(compiler)
243 (((s) + _DEBUG_NEW_ALIGNMENT - 1) & ~(_DEBUG_NEW_ALIGNMENT - 1))
255 const size_t PLATFORM_MEM_ALIGNMENT =
sizeof(size_t) * 2;
267 #if _DEBUG_NEW_FILENAME_LEN == 0
276 #if _DEBUG_NEW_REMEMBER_STACK_TRACE
300 #if _DEBUG_NEW_FILENAME_LEN == 0
308 #if _DEBUG_NEW_REMEMBER_STACK_TRACE
370 #if _DEBUG_NEW_USE_ADDR2LINE
382 static const void* last_addr =
_NULLPTR;
383 static char last_info[256] =
"";
384 if (addr == last_addr)
386 if (last_info[0] ==
'\0')
394 const char addr2line_cmd[] =
"atos -o ";
396 const char addr2line_cmd[] =
"addr2line -e ";
400 const int exeext_len = 4;
402 const int exeext_len = 0;
405 #if NVWA_UNIX && !NVWA_CYGWIN
406 const char ignore_err[] =
" 2>/dev/null";
407 #elif NVWA_CYGWIN || \
408 (NVWA_WIN32 && defined(WINVER) && WINVER >= 0x0500)
409 const char ignore_err[] =
" 2>nul";
411 const char ignore_err[] =
"";
415 +
sizeof addr2line_cmd - 1
416 +
sizeof ignore_err - 1
419 strcpy(cmd, addr2line_cmd);
421 size_t len = strlen(cmd);
424 || (strcmp(cmd + len - 4,
".exe") != 0 &&
425 strcmp(cmd + len - 4,
".EXE") != 0))
427 strcpy(cmd + len,
".exe");
431 sprintf(cmd + len,
" %p%s", addr, ignore_err);
432 FILE* fp = popen(cmd,
"r");
435 char buffer[
sizeof last_info] =
"";
437 if (fgets(buffer,
sizeof buffer, fp))
439 len = strlen(buffer);
440 if (buffer[len - 1] ==
'\n')
441 buffer[--len] =
'\0';
443 int res = pclose(fp);
448 if (res == 0 && len > 0)
451 if (buffer[len - 1] ==
'0' && buffer[len - 2] ==
':')
456 strcpy(last_info, buffer);
505 #if _DEBUG_NEW_REMEMBER_STACK_TRACE
517 static void print_stacktrace(
void** stacktrace)
522 for (
size_t i = 0; stacktrace[i] !=
_NULLPTR; ++i)
546 int line = ptr->
line;
548 #if _DEBUG_NEW_REMEMBER_STACK_TRACE
549 void** stacktrace = ptr->stacktrace;
557 #if _DEBUG_NEW_TAILCHECK
568 const unsigned char*
const tail_ptr = (
unsigned char*)ptr +
571 if (tail_ptr[i] != _DEBUG_NEW_TAILCHECK_CHAR)
587 static void*
alloc_mem(
size_t size,
const char* file,
int line,
bool is_array)
590 #if _DEBUG_NEW_TYPE == 1
592 Alignment_too_small);
595 Alignment_must_be_power_of_two);
601 #if _DEBUG_NEW_STD_OPER_NEW
606 "Out of memory when allocating %lu bytes\n",
607 (
unsigned long)
size);
613 #if _DEBUG_NEW_FILENAME_LEN == 0
620 ptr->
addr = (
void*)file;
623 #if _DEBUG_NEW_REMEMBER_STACK_TRACE
626 #if _DEBUG_NEW_REMEMBER_STACK_TRACE == 2
631 size_t buffer_length =
sizeof(buffer) /
sizeof(*buffer);
634 int stacktrace_length = backtrace(buffer,
int(buffer_length));
638 USHORT stacktrace_length = CaptureStackBackTrace(
639 0, DWORD(buffer_length), buffer,
_NULLPTR);
642 size_t stacktrace_size = stacktrace_length *
sizeof(
void*);
643 ptr->stacktrace = (
void**)malloc(stacktrace_size +
sizeof(
void*));
647 memcpy(ptr->stacktrace, buffer, stacktrace_size);
648 ptr->stacktrace[stacktrace_length] =
_NULLPTR;
662 #if _DEBUG_NEW_TAILCHECK
663 memset((
char*)usr_ptr +
size, _DEBUG_NEW_TAILCHECK_CHAR,
670 "new%s: allocated %p (size %lu, ",
671 is_array ?
"[]" :
"",
672 usr_ptr, (
unsigned long)
size);
702 is_array ?
"[]" :
"", usr_ptr);
714 msg =
"delete[] after new";
716 msg =
"delete after new[]";
719 "%s: pointer %p (size %lu)\n\tat ",
722 (
unsigned long)ptr->
size);
733 #if _DEBUG_NEW_TAILCHECK
734 if (!check_tail(ptr))
752 "delete%s: freed %p (size %lu, %lu bytes still allocated)\n",
753 is_array ?
"[]" :
"",
757 #if _DEBUG_NEW_REMEMBER_STACK_TRACE
758 free(ptr->stacktrace);
772 int whitelisted_leak_cnt = 0;
783 "warning: heap data corrupt near %p\n",
786 #if _DEBUG_NEW_TAILCHECK
787 if (!check_tail(ptr))
790 "warning: overwritten past end of object at %p\n",
797 ++whitelisted_leak_cnt;
802 "Leaked object at %p (size %lu, ",
804 (
unsigned long)ptr->
size);
813 #if _DEBUG_NEW_REMEMBER_STACK_TRACE
815 print_stacktrace(ptr->stacktrace);
824 if (whitelisted_leak_cnt > 0)
826 fprintf(
new_output_fp,
"*** %d leaks found (%d whitelisted)\n",
827 leak_cnt, whitelisted_leak_cnt);
849 fprintf(
new_output_fp,
"*** Checking for memory corruption: START\n");
861 #if _DEBUG_NEW_TAILCHECK
866 "Heap data corrupt near %p (size %lu, ",
868 (
unsigned long)ptr->
size);
869 #if _DEBUG_NEW_TAILCHECK
874 "Overwritten past end of object at %p (size %lu, ",
876 (
unsigned long)ptr->
size);
885 #if _DEBUG_NEW_REMEMBER_STACK_TRACE
887 print_stacktrace(ptr->stacktrace);
892 fprintf(
new_output_fp,
"*** Checking for memory corruption: %d FOUND\n",
912 size_t offset = (
char*)usr_ptr - (
char*)
_NULLPTR;
913 if (offset % PLATFORM_MEM_ALIGNMENT != 0) {
914 offset -=
sizeof(size_t);
915 if (offset % PLATFORM_MEM_ALIGNMENT != 0) {
918 "warning: memory unaligned; skipping processing (%s:%d)\n",
922 usr_ptr = (
char*)usr_ptr -
sizeof(
size_t);
931 "warning: debug_new used with placement new (%s:%d)\n",
938 "info: pointer %p allocated from %s:%d\n",
941 #if _DEBUG_NEW_FILENAME_LEN == 0
948 #if _DEBUG_NEW_REMEMBER_STACK_TRACE == 2
949 free(ptr->stacktrace);
977 #if defined(__GNUC__) && __GNUC__ == 3
978 if (!getenv(
"GLIBCPP_FORCE_NEW") && !getenv(
"GLIBCXX_FORCE_NEW"))
980 "*** WARNING: GCC 3 is detected, please make sure the environment\n"
981 " variable GLIBCPP_FORCE_NEW (GCC 3.2 and 3.3) or GLIBCXX_FORCE_NEW\n"
982 " (GCC 3.4) is defined. Check the README file for details.\n");
989 #if NVWA_USE_NAMESPACE
990 using namespace nvwa;
1003 void*
operator new(
size_t size,
const char* file,
int line)
1006 #if _DEBUG_NEW_STD_OPER_NEW
1010 throw std::bad_alloc();
1026 void*
operator new[](
size_t size,
const char* file,
int line)
1029 #if _DEBUG_NEW_STD_OPER_NEW
1033 throw std::bad_alloc();
1109 #if __cplusplus >= 201402L
1112 void operator delete(
void* ptr, size_t)
_NOEXCEPT
1117 void operator delete[](
void* ptr, size_t)
_NOEXCEPT
1134 void operator delete(
void* ptr,
const char* file,
int line)
_NOEXCEPT
1140 "info: exception thrown on initializing object at %p (",
1145 operator delete(ptr);
1156 void operator delete[](
void* ptr,
const char* file,
int line)
_NOEXCEPT
1162 "info: exception thrown on initializing objects at %p (",
1167 operator delete[](ptr);
1176 void operator delete(
void* ptr,
const std::nothrow_t&)
_NOEXCEPT
1187 void operator delete[](
void* ptr,
const std::nothrow_t&)
_NOEXCEPT
1193 #undef _DEBUG_NEW_REMEMBER_STACK_TRACE
#define NVWA_NAMESPACE_BEGIN
#define NVWA_NAMESPACE_END
void _M_process(void *ptr)
static void * alloc_mem(size_t size, const char *file, int line, bool is_array)
static void print_position(const void *ptr, int line)
static bool is_leak_whitelisted(new_ptr_list_t *ptr)
#define _DEBUG_NEW_ERROR_ACTION
#define _DEBUG_NEW_PROGNAME
#define _DEBUG_NEW_TAILCHECK
static size_t total_mem_alloc
const char * new_progname
#define _DEBUG_NEW_ALIGNMENT
static fast_mutex new_output_lock
static fast_mutex new_ptr_lock
static bool print_position_from_addr(const void *)
static void free_pointer(void *usr_ptr, void *addr, bool is_array)
static new_ptr_list_t new_ptr_list
static const unsigned DEBUG_NEW_MAGIC
#define _DEBUG_NEW_FILENAME_LEN
static const int ALIGNED_LIST_ITEM_SIZE
#define _DEBUG_NEW_CALLER_ADDRESS
leak_whitelist_callback_t leak_whitelist_callback
int check_mem_corruption()
stacktrace_print_callback_t stacktrace_print_callback
bool(* leak_whitelist_callback_t)(char const *file, int line, void *addr, void **stacktrace)
void(* stacktrace_print_callback_t)(FILE *fp, void **stacktrace)
PRAGMA45(GCC diagnostic push) PRAGMA45(GCC diagnostic ignored "-Wredundant-decls") PRAGMA45(GCC diagnostic pop) class TestMain
#define PRAGMACLANG6GCC(str)
bool msg(InputEvent &event)
#define STATIC_ASSERT(_Expr, _Msg)
new_ptr_list_t * prev
Pointer to the previous memory block.
new_ptr_list_t * next
Pointer to the next memory block.
char file[44]
File name of the caller.
unsigned is_array
Non-zero iff new[] is used.
size_t size
Size of the memory block.
unsigned magic
Magic number for error detection.
void * addr
Address of the caller to new.
unsigned line
Line number of the caller; or 0.