ManaPlus
Data Structures | Macros | Functions | Variables
debug_new.cpp File Reference

(986a3bf)

#include "localconsts.h"
#include <new>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "debug/nvwa/_nvwa.h"
#include "debug/nvwa/c++11.h"
#include "debug/nvwa/fast_mutex.h"
#include "debug/nvwa/static_assert.h"
#include "debug/nvwa/debug_new.h"

Go to the source code of this file.

Data Structures

struct  new_ptr_list_t
 

Macros

#define _DEBUG_NEW_REDEFINE_NEW   0
 
#define _DEBUG_NEW_ALIGNMENT   16
 
#define _DEBUG_NEW_CALLER_ADDRESS   _NULLPTR
 
#define _DEBUG_NEW_ERROR_ACTION   abort()
 
#define _DEBUG_NEW_FILENAME_LEN   44
 
#define _DEBUG_NEW_PROGNAME   _NULLPTR
 
#define _DEBUG_NEW_REMEMBER_STACK_TRACE   0
 
#define _DEBUG_NEW_STD_OPER_NEW   1
 
#define _DEBUG_NEW_TAILCHECK   0
 
#define _DEBUG_NEW_USE_ADDR2LINE   0
 
#define ALIGN(s)    (((s) + _DEBUG_NEW_ALIGNMENT - 1) & ~(_DEBUG_NEW_ALIGNMENT - 1))
 

Functions

static bool print_position_from_addr (const void *)
 
static void print_position (const void *ptr, int line)
 
static bool is_leak_whitelisted (new_ptr_list_t *ptr)
 
static void * alloc_mem (size_t size, const char *file, int line, bool is_array)
 
static void free_pointer (void *usr_ptr, void *addr, bool is_array)
 
int check_leaks ()
 
int check_mem_corruption ()
 
void * operator new (size_t size, const char *file, int line)
 
void * operator new[] (size_t size, const char *file, int line)
 
void * operator new (size_t size)
 
void * operator new[] (size_t size)
 
void * operator new (size_t size, const std::nothrow_t &) throw ()
 
void * operator new[] (size_t size, const std::nothrow_t &) throw ()
 
void operator delete (void *ptr) throw ()
 
void operator delete[] (void *ptr) throw ()
 
void operator delete (void *ptr, const char *file, int line) throw ()
 
void operator delete[] (void *ptr, const char *file, int line) throw ()
 
void operator delete (void *ptr, const std::nothrow_t &) throw ()
 
void operator delete[] (void *ptr, const std::nothrow_t &) throw ()
 

Variables

static const unsigned DEBUG_NEW_MAGIC = 0x4442474E
 
static const int ALIGNED_LIST_ITEM_SIZE = ((( sizeof(new_ptr_list_t) ) + 16 - 1) & ~( 16 - 1))
 
static new_ptr_list_t new_ptr_list
 
static fast_mutex new_ptr_lock
 
static fast_mutex new_output_lock
 
static size_t total_mem_alloc = 0
 
bool new_autocheck_flag = true
 
bool new_verbose_flag = false
 
FILE * new_output_fp = stderr
 
const char * new_progname = ((void *)0)
 
stacktrace_print_callback_t stacktrace_print_callback = ((void *)0)
 
leak_whitelist_callback_t leak_whitelist_callback = ((void *)0)
 

Detailed Description

Implementation of debug versions of new and delete to check leakage.

Date
2016-10-14

Definition in file debug_new.cpp.

Macro Definition Documentation

◆ _DEBUG_NEW_ALIGNMENT

#define _DEBUG_NEW_ALIGNMENT   16

◆ _DEBUG_NEW_CALLER_ADDRESS

#define _DEBUG_NEW_CALLER_ADDRESS   _NULLPTR

The expression to return the caller address. nvwa::print_position will later on use this address to print the position information of memory operation points.

◆ _DEBUG_NEW_ERROR_ACTION

#define _DEBUG_NEW_ERROR_ACTION   abort()

The action to take when an error occurs. The default behaviour is to call abort, unless _DEBUG_NEW_ERROR_CRASH is defined, in which case a segmentation fault will be triggered instead (which can be useful on platforms like Windows that do not generate a core dump when abort is called).

◆ _DEBUG_NEW_FILENAME_LEN

#define _DEBUG_NEW_FILENAME_LEN   44

The length of file name stored if greater than zero. If it is zero, only a const char pointer will be stored. Currently the default value is non-zero (thus to copy the file name) on non-Windows platforms, because I once found that the exit leakage check could not access the address of the file name on Linux (in my case, a core dump occurred when check_leaks tried to access the file name in a shared library after a SIGINT). This value makes the size of new_ptr_list_t 64 on non-Windows 32-bit platforms (w/o stack backtrace).

◆ _DEBUG_NEW_PROGNAME

#define _DEBUG_NEW_PROGNAME   _NULLPTR

The program (executable) name to be set at compile time. It is better to assign the full program path to nvwa::new_progname in main (at run time) than to use this (compile-time) macro, but this macro serves well as a quick hack. Note also that double quotation marks need to be used around the program name, i.e., one should specify a command-line option like -D_DEBUG_NEW_PROGNAME=\"a.out\" in bash, or -D_DEBUG_NEW_PROGNAME=\"a.exe\" in the Windows command prompt.

◆ _DEBUG_NEW_REDEFINE_NEW

#define _DEBUG_NEW_REDEFINE_NEW   0

◆ _DEBUG_NEW_REMEMBER_STACK_TRACE

#define _DEBUG_NEW_REMEMBER_STACK_TRACE   0

Macro to indicate whether stack traces of allocations should be included in NVWA allocation information and be printed while leaks are reported. Useful to pinpoint leaks caused by strdup and other custom allocation functions. It is also very helpful in filtering out false positives caused by internal STL/C runtime operations. It is off by default because it is quite memory heavy. Set it to 1 to make all allocations have stack trace attached, or set to 2 to make only allocations that lack calling source code information (file and line) have the stack trace attached.

◆ _DEBUG_NEW_STD_OPER_NEW

#define _DEBUG_NEW_STD_OPER_NEW   1

Macro to indicate whether the standard-conformant behaviour of operator new is wanted. It is on by default now, but the user may set it to 0 to revert to the old behaviour.

◆ _DEBUG_NEW_TAILCHECK

#define _DEBUG_NEW_TAILCHECK   0

Macro to indicate whether a writing-past-end check will be performed. Define it to a positive integer as the number of padding bytes at the end of a memory block for checking.

◆ _DEBUG_NEW_USE_ADDR2LINE

#define _DEBUG_NEW_USE_ADDR2LINE   0

Whether to use addr2line to convert a caller address to file/line information. Defining it to a non-zero value will enable the conversion (automatically done if GCC is detected). Defining it to zero will disable the conversion.

◆ ALIGN

#define ALIGN (   s)     (((s) + _DEBUG_NEW_ALIGNMENT - 1) & ~(_DEBUG_NEW_ALIGNMENT - 1))

Function Documentation

◆ alloc_mem()

static void* alloc_mem ( size_t  size,
const char *  file,
int  line,
bool  is_array 
)
static

Allocates memory and initializes control data.

Parameters
sizesize of the required memory block
filenull-terminated string of the file name
lineline number
is_arrayboolean value whether this is an array operation
Returns
pointer to the user-requested memory area; null if memory allocation is not successful

Definition at line 587 of file debug_new.cpp.

588 {
589  assert(line >= 0);
590 #if _DEBUG_NEW_TYPE == 1
591  STATIC_ASSERT(_DEBUG_NEW_ALIGNMENT >= PLATFORM_MEM_ALIGNMENT,
592  Alignment_too_small);
593 #endif
595  Alignment_must_be_power_of_two);
596  STATIC_ASSERT(_DEBUG_NEW_TAILCHECK >= 0, Invalid_tail_check_length);
598  new_ptr_list_t* ptr = (new_ptr_list_t*)malloc(s);
599  if (ptr == _NULLPTR)
600  {
601 #if _DEBUG_NEW_STD_OPER_NEW
602  return _NULLPTR;
603 #else
605  fprintf(new_output_fp,
606  "Out of memory when allocating %lu bytes\n",
607  (unsigned long)size);
608  fflush(new_output_fp);
610 #endif
611  }
612  void* usr_ptr = (char*)ptr + ALIGNED_LIST_ITEM_SIZE;
613 #if _DEBUG_NEW_FILENAME_LEN == 0
614  ptr->file = file;
615 #else
616  if (line)
617  strncpy(ptr->file, file, _DEBUG_NEW_FILENAME_LEN - 1)
618  [_DEBUG_NEW_FILENAME_LEN - 1] = '\0';
619  else
620  ptr->addr = (void*)file;
621 #endif
622  ptr->line = line;
623 #if _DEBUG_NEW_REMEMBER_STACK_TRACE
624  ptr->stacktrace = _NULLPTR;
625 
626 #if _DEBUG_NEW_REMEMBER_STACK_TRACE == 2
627  if (line == 0)
628 #endif
629  {
630  void* buffer [255];
631  size_t buffer_length = sizeof(buffer) / sizeof(*buffer);
632 
633 #if NVWA_UNIX
634  int stacktrace_length = backtrace(buffer, int(buffer_length));
635 #endif
636 
637 #if NVWA_WINDOWS
638  USHORT stacktrace_length = CaptureStackBackTrace(
639  0, DWORD(buffer_length), buffer, _NULLPTR);
640 #endif
641 
642  size_t stacktrace_size = stacktrace_length * sizeof(void*);
643  ptr->stacktrace = (void**)malloc(stacktrace_size + sizeof(void*));
644 
645  if (ptr->stacktrace != _NULLPTR)
646  {
647  memcpy(ptr->stacktrace, buffer, stacktrace_size);
648  ptr->stacktrace[stacktrace_length] = _NULLPTR;
649  }
650  }
651 #endif
652  ptr->is_array = is_array;
653  ptr->size = size;
654  ptr->magic = DEBUG_NEW_MAGIC;
655  {
657  ptr->prev = new_ptr_list.prev;
658  ptr->next = &new_ptr_list;
659  new_ptr_list.prev->next = ptr;
660  new_ptr_list.prev = ptr;
661  }
662 #if _DEBUG_NEW_TAILCHECK
663  memset((char*)usr_ptr + size, _DEBUG_NEW_TAILCHECK_CHAR,
665 #endif
666  if (new_verbose_flag)
667  {
669  fprintf(new_output_fp,
670  "new%s: allocated %p (size %lu, ",
671  is_array ? "[]" : "",
672  usr_ptr, (unsigned long)size);
673  if (line != 0)
674  print_position(ptr->file, ptr->line);
675  else
676  print_position(ptr->addr, ptr->line);
677  fprintf(new_output_fp, ")\n");
678  }
680  return usr_ptr;
681 }
#define _NULLPTR
Definition: c++11.h:327
static void print_position(const void *ptr, int line)
Definition: debug_new.cpp:488
#define _DEBUG_NEW_ERROR_ACTION
#define _DEBUG_NEW_TAILCHECK
static size_t total_mem_alloc
Definition: debug_new.cpp:327
#define _DEBUG_NEW_ALIGNMENT
static fast_mutex new_output_lock
Definition: debug_new.cpp:322
bool new_verbose_flag
Definition: debug_new.cpp:338
static fast_mutex new_ptr_lock
Definition: debug_new.cpp:317
static new_ptr_list_t new_ptr_list
Definition: debug_new.cpp:295
static const unsigned DEBUG_NEW_MAGIC
Definition: debug_new.cpp:285
#define _DEBUG_NEW_FILENAME_LEN
static const int ALIGNED_LIST_ITEM_SIZE
Definition: debug_new.cpp:290
FILE * new_output_fp
Definition: debug_new.cpp:345
int size()
Definition: emotedb.cpp:306
#define STATIC_ASSERT(_Expr, _Msg)
Definition: static_assert.h:52
new_ptr_list_t * prev
Pointer to the previous memory block.
Definition: debug_new.cpp:263
new_ptr_list_t * next
Pointer to the next memory block.
Definition: debug_new.cpp:262
char file[44]
File name of the caller.
Definition: debug_new.cpp:270
unsigned is_array
Non-zero iff new[] is used.
Definition: debug_new.cpp:275
size_t size
Size of the memory block.
Definition: debug_new.cpp:264
unsigned magic
Magic number for error detection.
Definition: debug_new.cpp:279
void * addr
Address of the caller to new.
Definition: debug_new.cpp:272
unsigned line
Line number of the caller; or 0.
Definition: debug_new.cpp:274

References _DEBUG_NEW_ALIGNMENT, _DEBUG_NEW_ERROR_ACTION, _DEBUG_NEW_FILENAME_LEN, _DEBUG_NEW_TAILCHECK, _NULLPTR, new_ptr_list_t::addr, ALIGNED_LIST_ITEM_SIZE, DEBUG_NEW_MAGIC, new_ptr_list_t::file, new_ptr_list_t::is_array, new_ptr_list_t::line, new_ptr_list_t::magic, new_output_fp, new_output_lock, new_ptr_list, new_ptr_lock, new_verbose_flag, new_ptr_list_t::next, new_ptr_list_t::prev, print_position(), new_ptr_list_t::size, EmoteDB::size(), STATIC_ASSERT, and total_mem_alloc.

Referenced by operator new(), and operator new[]().

◆ check_leaks()

int check_leaks ( )

Checks for memory leaks.

Returns
zero if no leakage is found; the number of leaks otherwise

Definition at line 769 of file debug_new.cpp.

770 {
771  int leak_cnt = 0;
772  int whitelisted_leak_cnt = 0;
776 
777  while (ptr != &new_ptr_list)
778  {
779  const char* const usr_ptr = (char*)ptr + ALIGNED_LIST_ITEM_SIZE;
780  if (ptr->magic != DEBUG_NEW_MAGIC)
781  {
782  fprintf(new_output_fp,
783  "warning: heap data corrupt near %p\n",
784  usr_ptr);
785  }
786 #if _DEBUG_NEW_TAILCHECK
787  if (!check_tail(ptr))
788  {
789  fprintf(new_output_fp,
790  "warning: overwritten past end of object at %p\n",
791  usr_ptr);
792  }
793 #endif
794 
795  if (is_leak_whitelisted(ptr))
796  {
797  ++whitelisted_leak_cnt;
798  }
799  else
800  {
801  fprintf(new_output_fp,
802  "Leaked object at %p (size %lu, ",
803  usr_ptr,
804  (unsigned long)ptr->size);
805 
806  if (ptr->line != 0)
807  print_position(ptr->file, ptr->line);
808  else
809  print_position(ptr->addr, ptr->line);
810 
811  fprintf(new_output_fp, ")\n");
812 
813 #if _DEBUG_NEW_REMEMBER_STACK_TRACE
814  if (ptr->stacktrace != _NULLPTR)
815  print_stacktrace(ptr->stacktrace);
816 #endif
817  }
818 
819  ptr = ptr->next;
820  ++leak_cnt;
821  }
822  if (new_verbose_flag || leak_cnt)
823  {
824  if (whitelisted_leak_cnt > 0)
825  {
826  fprintf(new_output_fp, "*** %d leaks found (%d whitelisted)\n",
827  leak_cnt, whitelisted_leak_cnt);
828  }
829  else
830  {
831  fprintf(new_output_fp, "*** %d leaks found\n", leak_cnt);
832  }
833  }
834 
835  return leak_cnt;
836 }
static bool is_leak_whitelisted(new_ptr_list_t *ptr)
Definition: debug_new.cpp:540

References _NULLPTR, new_ptr_list_t::addr, ALIGNED_LIST_ITEM_SIZE, DEBUG_NEW_MAGIC, new_ptr_list_t::file, is_leak_whitelisted(), new_ptr_list_t::line, new_ptr_list_t::magic, new_output_fp, new_output_lock, new_ptr_list, new_ptr_lock, new_verbose_flag, new_ptr_list_t::next, print_position(), and new_ptr_list_t::size.

Referenced by debug_new_counter::~debug_new_counter().

◆ check_mem_corruption()

int check_mem_corruption ( )

Checks for heap corruption.

Returns
zero if no problem is found; the number of found memory corruptions otherwise

Definition at line 844 of file debug_new.cpp.

845 {
846  int corrupt_cnt = 0;
849  fprintf(new_output_fp, "*** Checking for memory corruption: START\n");
850  for (new_ptr_list_t* ptr = new_ptr_list.next;
851  ptr != &new_ptr_list;
852  ptr = ptr->next)
853  {
854  const char* const usr_ptr = (char*)ptr + ALIGNED_LIST_ITEM_SIZE;
855  if (ptr->magic == DEBUG_NEW_MAGIC
857  && check_tail(ptr)
858 #endif
859  )
860  continue;
861 #if _DEBUG_NEW_TAILCHECK
862  if (ptr->magic != DEBUG_NEW_MAGIC)
863  {
864 #endif
865  fprintf(new_output_fp,
866  "Heap data corrupt near %p (size %lu, ",
867  usr_ptr,
868  (unsigned long)ptr->size);
869 #if _DEBUG_NEW_TAILCHECK
870  }
871  else
872  {
873  fprintf(new_output_fp,
874  "Overwritten past end of object at %p (size %lu, ",
875  usr_ptr,
876  (unsigned long)ptr->size);
877  }
878 #endif
879  if (ptr->line != 0)
880  print_position(ptr->file, ptr->line);
881  else
882  print_position(ptr->addr, ptr->line);
883  fprintf(new_output_fp, ")\n");
884 
885 #if _DEBUG_NEW_REMEMBER_STACK_TRACE
886  if (ptr->stacktrace != _NULLPTR)
887  print_stacktrace(ptr->stacktrace);
888 #endif
889 
890  ++corrupt_cnt;
891  }
892  fprintf(new_output_fp, "*** Checking for memory corruption: %d FOUND\n",
893  corrupt_cnt);
894  return corrupt_cnt;
895 }

References _DEBUG_NEW_TAILCHECK, _NULLPTR, new_ptr_list_t::addr, ALIGNED_LIST_ITEM_SIZE, DEBUG_NEW_MAGIC, new_ptr_list_t::file, new_ptr_list_t::line, new_ptr_list_t::magic, new_output_fp, new_output_lock, new_ptr_list, new_ptr_lock, new_ptr_list_t::next, print_position(), and new_ptr_list_t::size.

Referenced by free_pointer().

◆ free_pointer()

static void free_pointer ( void *  usr_ptr,
void *  addr,
bool  is_array 
)
static

Frees memory and adjusts pointers.

Parameters
usr_ptrpointer to the previously allocated memory
addrpointer to the caller
is_arrayflag indicating whether it is invoked by a delete[] call

Definition at line 691 of file debug_new.cpp.

692 {
693  if (usr_ptr == _NULLPTR)
694  return;
695  new_ptr_list_t* ptr =
696  (new_ptr_list_t*)((char*)usr_ptr - ALIGNED_LIST_ITEM_SIZE);
697  if (ptr->magic != DEBUG_NEW_MAGIC)
698  {
699  {
701  fprintf(new_output_fp, "delete%s: invalid pointer %p (",
702  is_array ? "[]" : "", usr_ptr);
703  print_position(addr, 0);
704  fprintf(new_output_fp, ")\n");
705  }
707  fflush(new_output_fp);
709  }
710  if (is_array != ptr->is_array)
711  {
712  const char* msg;
713  if (is_array)
714  msg = "delete[] after new";
715  else
716  msg = "delete after new[]";
718  fprintf(new_output_fp,
719  "%s: pointer %p (size %lu)\n\tat ",
720  msg,
721  (char*)ptr + ALIGNED_LIST_ITEM_SIZE,
722  (unsigned long)ptr->size);
723  print_position(addr, 0);
724  fprintf(new_output_fp, "\n\toriginally allocated at ");
725  if (ptr->line != 0)
726  print_position(ptr->file, ptr->line);
727  else
728  print_position(ptr->addr, ptr->line);
729  fprintf(new_output_fp, "\n");
730  fflush(new_output_fp);
732  }
733 #if _DEBUG_NEW_TAILCHECK
734  if (!check_tail(ptr))
735  {
737  fflush(new_output_fp);
739  }
740 #endif
741  {
743  total_mem_alloc -= ptr->size;
744  ptr->magic = 0;
745  ptr->prev->next = ptr->next;
746  ptr->next->prev = ptr->prev;
747  }
748  if (new_verbose_flag)
749  {
751  fprintf(new_output_fp,
752  "delete%s: freed %p (size %lu, %lu bytes still allocated)\n",
753  is_array ? "[]" : "",
754  (char*)ptr + ALIGNED_LIST_ITEM_SIZE,
755  (unsigned long)ptr->size, (unsigned long)total_mem_alloc);
756  }
757 #if _DEBUG_NEW_REMEMBER_STACK_TRACE
758  free(ptr->stacktrace);
759 #endif
760  free(ptr);
761  return;
762 }
int check_mem_corruption()
Definition: debug_new.cpp:844
bool msg(InputEvent &event)
Definition: chat.cpp:39

References _DEBUG_NEW_ERROR_ACTION, _NULLPTR, new_ptr_list_t::addr, ALIGNED_LIST_ITEM_SIZE, check_mem_corruption(), DEBUG_NEW_MAGIC, new_ptr_list_t::file, new_ptr_list_t::is_array, new_ptr_list_t::line, new_ptr_list_t::magic, Actions::msg(), new_output_fp, new_output_lock, new_ptr_lock, new_verbose_flag, new_ptr_list_t::next, new_ptr_list_t::prev, print_position(), new_ptr_list_t::size, and total_mem_alloc.

Referenced by operator delete(), and operator delete[]().

◆ is_leak_whitelisted()

static bool is_leak_whitelisted ( new_ptr_list_t ptr)
static

Checks whether a leak should be ignored. Its runtime performance depends on the callback nvwa::leak_whitelist_callback.

Parameters
ptrpointer to a new_ptr_list_t struct
Returns
true if the leak should be whitelisted; false otherwise

Definition at line 540 of file debug_new.cpp.

541 {
543  return false;
544 
545  char const* file = ptr->line != 0 ? ptr->file : _NULLPTR;
546  int line = ptr->line;
547  void* addr = ptr->line == 0 ? ptr->addr : _NULLPTR;
548 #if _DEBUG_NEW_REMEMBER_STACK_TRACE
549  void** stacktrace = ptr->stacktrace;
550 #else
551  void** stacktrace = _NULLPTR;
552 #endif
553 
554  return leak_whitelist_callback(file, line, addr, stacktrace);
555 }
leak_whitelist_callback_t leak_whitelist_callback
Definition: debug_new.cpp:368

References _NULLPTR, new_ptr_list_t::addr, new_ptr_list_t::file, leak_whitelist_callback, and new_ptr_list_t::line.

Referenced by check_leaks().

◆ operator delete() [1/3]

void operator delete ( void *  ptr)
throw (
)

Deallocates memory.

Parameters
ptrpointer to the previously allocated memory

Definition at line 1094 of file debug_new.cpp.

1095 {
1097 }
static void free_pointer(void *usr_ptr, void *addr, bool is_array)
Definition: debug_new.cpp:691
#define _DEBUG_NEW_CALLER_ADDRESS

References _DEBUG_NEW_CALLER_ADDRESS, and free_pointer().

◆ operator delete() [2/3]

void operator delete ( void *  ptr,
const char *  file,
int  line 
)
throw (
)

Placement deallocation function. For details, please check Section 5.3.4 of the C++ 1998 or 2011 Standard.

Parameters
ptrpointer to the previously allocated memory
filenull-terminated string of the file name
lineline number
See also
http://www.csci.csusb.edu/dick/c++std/cd2/expr.html#expr.new
http://wyw.dcweb.cn/leakage.htm

Definition at line 1134 of file debug_new.cpp.

1135 {
1136  if (new_verbose_flag)
1137  {
1139  fprintf(new_output_fp,
1140  "info: exception thrown on initializing object at %p (",
1141  ptr);
1142  print_position(file, line);
1143  fprintf(new_output_fp, ")\n");
1144  }
1145  operator delete(ptr);
1146 }

References new_output_fp, new_output_lock, new_verbose_flag, and print_position().

◆ operator delete() [3/3]

void operator delete ( void *  ptr,
const std::nothrow_t &   
)
throw (
)

Placement deallocation function. For details, please check Section 5.3.4 of the C++ 1998 or 2011 Standard.

Parameters
ptrpointer to the previously allocated memory

Definition at line 1176 of file debug_new.cpp.

1177 {
1178  operator delete(ptr, (char*)_DEBUG_NEW_CALLER_ADDRESS, 0);
1179 }

References _DEBUG_NEW_CALLER_ADDRESS.

◆ operator delete[]() [1/3]

void operator delete[] ( void *  ptr)
throw (
)

Deallocates array memory.

Parameters
ptrpointer to the previously allocated memory

Definition at line 1104 of file debug_new.cpp.

1105 {
1107 }

References _DEBUG_NEW_CALLER_ADDRESS, and free_pointer().

◆ operator delete[]() [2/3]

void operator delete[] ( void *  ptr,
const char *  file,
int  line 
)
throw (
)

Placement deallocation function. For details, please check Section 5.3.4 of the C++ 1998 or 2011 Standard.

Parameters
ptrpointer to the previously allocated memory
filenull-terminated string of the file name
lineline number

Definition at line 1156 of file debug_new.cpp.

1157 {
1158  if (new_verbose_flag)
1159  {
1161  fprintf(new_output_fp,
1162  "info: exception thrown on initializing objects at %p (",
1163  ptr);
1164  print_position(file, line);
1165  fprintf(new_output_fp, ")\n");
1166  }
1167  operator delete[](ptr);
1168 }

References new_output_fp, new_output_lock, new_verbose_flag, and print_position().

◆ operator delete[]() [3/3]

void operator delete[] ( void *  ptr,
const std::nothrow_t &   
)
throw (
)

Placement deallocation function. For details, please check Section 5.3.4 of the C++ 1998 or 2011 Standard.

Parameters
ptrpointer to the previously allocated memory

Definition at line 1187 of file debug_new.cpp.

1188 {
1189  operator delete[](ptr, (char*)_DEBUG_NEW_CALLER_ADDRESS, 0);
1190 }

References _DEBUG_NEW_CALLER_ADDRESS.

◆ operator new() [1/3]

void* operator new ( size_t  size)

Allocates memory without file/line information.

Parameters
sizesize of the required memory block
Returns
pointer to the memory allocated; or null if memory is insufficient (_DEBUG_NEW_STD_OPER_NEW is 0)
Exceptions
bad_allocmemory is insufficient (_DEBUG_NEW_STD_OPER_NEW is 1)

Definition at line 1047 of file debug_new.cpp.

1048 {
1049  return operator new(size, (char*)_DEBUG_NEW_CALLER_ADDRESS, 0);
1050 }

References _DEBUG_NEW_CALLER_ADDRESS, and EmoteDB::size().

◆ operator new() [2/3]

void* operator new ( size_t  size,
const char *  file,
int  line 
)

Allocates memory with file/line information.

Parameters
sizesize of the required memory block
filenull-terminated string of the file name
lineline number
Returns
pointer to the memory allocated; or null if memory is insufficient (_DEBUG_NEW_STD_OPER_NEW is 0)
Exceptions
bad_allocmemory is insufficient (_DEBUG_NEW_STD_OPER_NEW is 1)

Definition at line 1003 of file debug_new.cpp.

1004 {
1005  void* ptr = alloc_mem(size, file, line, false);
1006 #if _DEBUG_NEW_STD_OPER_NEW
1007  if (ptr)
1008  return ptr;
1009  else
1010  throw std::bad_alloc();
1011 #else
1012  return ptr;
1013 #endif
1014 }
static void * alloc_mem(size_t size, const char *file, int line, bool is_array)
Definition: debug_new.cpp:587

References alloc_mem(), and EmoteDB::size().

◆ operator new() [3/3]

void* operator new ( size_t  size,
const std::nothrow_t &   
)
throw (
)

Allocates memory with no-throw guarantee.

Parameters
sizesize of the required memory block
Returns
pointer to the memory allocated; or null if memory is insufficient

Definition at line 1072 of file debug_new.cpp.

1073 {
1074  return alloc_mem(size, (char*)_DEBUG_NEW_CALLER_ADDRESS, 0, false);
1075 }

References _DEBUG_NEW_CALLER_ADDRESS, alloc_mem(), and EmoteDB::size().

◆ operator new[]() [1/3]

void* operator new[] ( size_t  size)

Allocates array memory without file/line information.

Parameters
sizesize of the required memory block
Returns
pointer to the memory allocated; or null if memory is insufficient (_DEBUG_NEW_STD_OPER_NEW is 0)
Exceptions
bad_allocmemory is insufficient (_DEBUG_NEW_STD_OPER_NEW is 1)

Definition at line 1060 of file debug_new.cpp.

1061 {
1062  return operator new[](size, (char*)_DEBUG_NEW_CALLER_ADDRESS, 0);
1063 }

References _DEBUG_NEW_CALLER_ADDRESS, and EmoteDB::size().

◆ operator new[]() [2/3]

void* operator new[] ( size_t  size,
const char *  file,
int  line 
)

Allocates array memory with file/line information.

Parameters
sizesize of the required memory block
filenull-terminated string of the file name
lineline number
Returns
pointer to the memory allocated; or null if memory is insufficient (_DEBUG_NEW_STD_OPER_NEW is 0)
Exceptions
bad_allocmemory is insufficient (_DEBUG_NEW_STD_OPER_NEW is 1)

Definition at line 1026 of file debug_new.cpp.

1027 {
1028  void* ptr = alloc_mem(size, file, line, true);
1029 #if _DEBUG_NEW_STD_OPER_NEW
1030  if (ptr)
1031  return ptr;
1032  else
1033  throw std::bad_alloc();
1034 #else
1035  return ptr;
1036 #endif
1037 }

References alloc_mem(), and EmoteDB::size().

◆ operator new[]() [3/3]

void* operator new[] ( size_t  size,
const std::nothrow_t &   
)
throw (
)

Allocates array memory with no-throw guarantee.

Parameters
sizesize of the required memory block
Returns
pointer to the memory allocated; or null if memory is insufficient

Definition at line 1084 of file debug_new.cpp.

1085 {
1086  return alloc_mem(size, (char*)_DEBUG_NEW_CALLER_ADDRESS, 0, true);
1087 }

References _DEBUG_NEW_CALLER_ADDRESS, alloc_mem(), and EmoteDB::size().

◆ print_position()

static void print_position ( const void *  ptr,
int  line 
)
static

Prints the position information of a memory operation point. When _DEBUG_NEW_USE_ADDR2LINE is defined to a non-zero value, this function will try to convert a given caller address to file/line information with addr2line.

Parameters
ptrsource file name if line is non-zero; caller address otherwise
linesource line number if non-zero; indication that ptr is the caller address otherwise

Definition at line 488 of file debug_new.cpp.

489 {
490  if (line != 0) // Is file/line information present?
491  {
492  fprintf(new_output_fp, "%s:%d", (const char*)ptr, line);
493  }
494  else if (ptr != _NULLPTR) // Is caller address present?
495  {
496  if (!print_position_from_addr(ptr)) // Fail to get source position?
497  fprintf(new_output_fp, "%p", ptr);
498  }
499  else // No information is present
500  {
501  fprintf(new_output_fp, "<Unknown>");
502  }
503 }
static bool print_position_from_addr(const void *)
Definition: debug_new.cpp:471

References _NULLPTR, new_output_fp, and print_position_from_addr().

Referenced by alloc_mem(), check_leaks(), check_mem_corruption(), free_pointer(), operator delete(), and operator delete[]().

◆ print_position_from_addr()

static bool print_position_from_addr ( const void *  )
static

Tries printing the position information from an instruction address. This is the stub version that does nothing at all.

Returns
false always

Definition at line 471 of file debug_new.cpp.

472 {
473  return false;
474 }

Referenced by print_position().

Variable Documentation

◆ ALIGNED_LIST_ITEM_SIZE

const int ALIGNED_LIST_ITEM_SIZE = ((( sizeof(new_ptr_list_t) ) + 16 - 1) & ~( 16 - 1))
static

The extra memory allocated by operator new.

Definition at line 290 of file debug_new.cpp.

Referenced by debug_new_recorder::_M_process(), alloc_mem(), check_leaks(), check_mem_corruption(), and free_pointer().

◆ DEBUG_NEW_MAGIC

const unsigned DEBUG_NEW_MAGIC = 0x4442474E
static

Definition of the constant magic number used for error detection.

Definition at line 285 of file debug_new.cpp.

Referenced by debug_new_recorder::_M_process(), alloc_mem(), check_leaks(), check_mem_corruption(), and free_pointer().

◆ leak_whitelist_callback

leak_whitelist_callback_t leak_whitelist_callback = ((void *)0)

Pointer to the callback used to filter out false positives from leak reports. A null value means the lack of filtering.

Definition at line 368 of file debug_new.cpp.

Referenced by is_leak_whitelisted().

◆ new_autocheck_flag

bool new_autocheck_flag = true

Flag to control whether nvwa::check_leaks will be automatically called on program exit.

Definition at line 333 of file debug_new.cpp.

Referenced by debug_new_counter::~debug_new_counter().

◆ new_output_fp

FILE* new_output_fp = stderr

Pointer to the output stream. The default output is stderr, and one may change it to a user stream if needed (say, new_verbose_flag is true and there are a lot of (de)allocations).

Definition at line 345 of file debug_new.cpp.

Referenced by debug_new_recorder::_M_process(), alloc_mem(), check_leaks(), check_mem_corruption(), free_pointer(), operator delete(), operator delete[](), print_position(), and debug_new_counter::~debug_new_counter().

◆ new_output_lock

fast_mutex new_output_lock
static

The mutex guard to protect simultaneous output to new_output_fp.

Definition at line 322 of file debug_new.cpp.

Referenced by debug_new_recorder::_M_process(), alloc_mem(), check_leaks(), check_mem_corruption(), free_pointer(), operator delete(), and operator delete[]().

◆ new_progname

const char* new_progname = ((void *)0)

Pointer to the program name. Its initial value is the macro _DEBUG_NEW_PROGNAME. You should try to assign the program path to it early in your application. Assigning argv[0] to it in main is one way. If you use bash or ksh (or similar), the following statement is probably what you want: ‘new_progname = getenv("_");’.

Definition at line 355 of file debug_new.cpp.

◆ new_ptr_list

new_ptr_list_t new_ptr_list
static
Initial value:
= {
0,
{
""
},
0,
0,
}

List of all new'd pointers.

Definition at line 295 of file debug_new.cpp.

Referenced by alloc_mem(), check_leaks(), and check_mem_corruption().

◆ new_ptr_lock

fast_mutex new_ptr_lock
static

The mutex guard to protect simultaneous access to the pointer list.

Definition at line 317 of file debug_new.cpp.

Referenced by alloc_mem(), check_leaks(), check_mem_corruption(), and free_pointer().

◆ new_verbose_flag

bool new_verbose_flag = false

Flag to control whether verbose messages are output.

Definition at line 338 of file debug_new.cpp.

Referenced by debug_new_recorder::_M_process(), alloc_mem(), check_leaks(), free_pointer(), operator delete(), operator delete[](), and debug_new_counter::~debug_new_counter().

◆ stacktrace_print_callback

stacktrace_print_callback_t stacktrace_print_callback = ((void *)0)

Pointer to the callback used to print the stack backtrace in case of a memory problem. A null value causes the default stack trace printing routine to be used.

Definition at line 362 of file debug_new.cpp.

◆ total_mem_alloc

size_t total_mem_alloc = 0
static

Total memory allocated in bytes.

Definition at line 327 of file debug_new.cpp.

Referenced by alloc_mem(), and free_pointer().