ManaPlus
debug_new.cpp
Go to the documentation of this file.
1 // -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
2 // vim:tabstop=4:shiftwidth=4:expandtab:
3 
4 /*
5  * Copyright (C) 2004-2016 Wu Yongwei <adah at users dot sourceforge dot net>
6  *
7  * This software is provided 'as-is', without any express or implied
8  * warranty. In no event will the authors be held liable for any
9  * damages arising from the use of this software.
10  *
11  * Permission is granted to anyone to use this software for any purpose,
12  * including commercial applications, and to alter it and redistribute
13  * it freely, subject to the following restrictions:
14  *
15  * 1. The origin of this software must not be misrepresented; you must
16  * not claim that you wrote the original software. If you use this
17  * software in a product, an acknowledgement in the product
18  * documentation would be appreciated but is not required.
19  * 2. Altered source versions must be plainly marked as such, and must
20  * not be misrepresented as being the original software.
21  * 3. This notice may not be removed or altered from any source
22  * distribution.
23  *
24  * This file is part of Stones of Nvwa:
25  * http://sourceforge.net/projects/nvwa
26  *
27  */
28 
37 #include "localconsts.h"
38 
39 PRAGMACLANG6GCC(GCC diagnostic push)
40 PRAGMACLANG6GCC(GCC diagnostic ignored "-Wold-style-cast")
41 
42 PRAGMA45(GCC diagnostic push)
43 PRAGMA45(GCC diagnostic ignored "-Wcast-qual")
44 
45 #include <new> // std::bad_alloc/nothrow_t
46 #include <assert.h> // assert
47 #include <stdio.h> // fprintf/stderr
48 #include <stdlib.h> // abort
49 #include <string.h> // strcpy/strncpy/sprintf
50 #include "debug/nvwa/_nvwa.h" // NVWA macros
51 
52 #if NVWA_UNIX
53 #include <alloca.h> // alloca
54 #endif
55 #if NVWA_WIN32
56 #include <malloc.h> // alloca
57 #endif
58 
59 #if NVWA_LINUX || NVWA_APPLE
60 #include <execinfo.h> // backtrace
61 #endif
62 
63 #if NVWA_WINDOWS
64 #ifndef WIN32_LEAN_AND_MEAN
65 #define WIN32_LEAN_AND_MEAN
66 #endif
67 #include <windows.h> // CaptureStackBackTrace
68 #endif
69 
70 #include "debug/nvwa/c++11.h" // _NOEXCEPT/_NULLPTR
71 #include "debug/nvwa/fast_mutex.h" // nvwa::fast_mutex
72 #include "debug/nvwa/static_assert.h" // STATIC_ASSERT
73 
74 #undef _DEBUG_NEW_EMULATE_MALLOC
75 #undef _DEBUG_NEW_REDEFINE_NEW
80 #define _DEBUG_NEW_REDEFINE_NEW 0
81 #include "debug/nvwa/debug_new.h"
82 
83 #if !_FAST_MUTEX_CHECK_INITIALIZATION && !defined(_NOTHREADS)
84 #error "_FAST_MUTEX_CHECK_INITIALIZATION not set: check_leaks may not work"
85 #endif
86 
93 #ifndef _DEBUG_NEW_ALIGNMENT
94 #define _DEBUG_NEW_ALIGNMENT 16
95 #endif
96 
104 #ifndef _DEBUG_NEW_CALLER_ADDRESS
105 #ifdef __GNUC__
106 #define _DEBUG_NEW_CALLER_ADDRESS __builtin_return_address(0)
107 #else
108 #define _DEBUG_NEW_CALLER_ADDRESS _NULLPTR
109 #endif
110 #endif
111 
121 #ifndef _DEBUG_NEW_ERROR_ACTION
122 #ifndef _DEBUG_NEW_ERROR_CRASH
123 #define _DEBUG_NEW_ERROR_ACTION abort()
124 #else
125 #define _DEBUG_NEW_ERROR_ACTION do { *((char*)0) = 0; abort(); } while (0)
126 #endif
127 #endif
128 
142 #ifndef _DEBUG_NEW_FILENAME_LEN
143 #if NVWA_WINDOWS
144 #define _DEBUG_NEW_FILENAME_LEN 0
145 #else
146 #define _DEBUG_NEW_FILENAME_LEN 44
147 #endif
148 #endif
149 
162 #ifndef _DEBUG_NEW_PROGNAME
163 #define _DEBUG_NEW_PROGNAME _NULLPTR
164 #endif
165 
179 #ifndef _DEBUG_NEW_REMEMBER_STACK_TRACE
180 #define _DEBUG_NEW_REMEMBER_STACK_TRACE 0
181 #endif
182 
190 #ifndef _DEBUG_NEW_STD_OPER_NEW
191 #define _DEBUG_NEW_STD_OPER_NEW 1
192 #endif
193 
201 #ifndef _DEBUG_NEW_TAILCHECK
202 #define _DEBUG_NEW_TAILCHECK 0
203 #endif
204 
210 //#ifndef _DEBUG_NEW_TAILCHECK_CHAR
211 //#define _DEBUG_NEW_TAILCHECK_CHAR 0xCC
212 //#endif
213 
222 #ifndef _DEBUG_NEW_USE_ADDR2LINE
223 #ifdef __GNUC__
224 #define _DEBUG_NEW_USE_ADDR2LINE 1
225 #else
226 #define _DEBUG_NEW_USE_ADDR2LINE 0
227 #endif
228 #endif
229 
230 #ifdef _MSC_VER
231 #pragma warning(disable: 4074) // #pragma init_seg(compiler) used
232 #pragma warning(disable: 4290) // C++ exception specification ignored
233 #if _MSC_VER >= 1400 // Visual Studio 2005 or later
234 #pragma warning(disable: 4996) // Use the `unsafe' strncpy
235 #endif
236 #pragma init_seg(compiler)
237 #endif
238 
242 #define ALIGN(s) \
243  (((s) + _DEBUG_NEW_ALIGNMENT - 1) & ~(_DEBUG_NEW_ALIGNMENT - 1))
244 
246 
255 const size_t PLATFORM_MEM_ALIGNMENT = sizeof(size_t) * 2;
256 
261 {
264  size_t size;
265  union
266  {
267 #if _DEBUG_NEW_FILENAME_LEN == 0
268  const char* file;
269 #else
271 #endif
272  void* addr;
273  };
274  unsigned line :31;
275  unsigned is_array:1;
276 #if _DEBUG_NEW_REMEMBER_STACK_TRACE
277  void** stacktrace;
278 #endif
279  unsigned magic;
280 };
281 
285 static const unsigned DEBUG_NEW_MAGIC = 0x4442474E;
286 
290 static const int ALIGNED_LIST_ITEM_SIZE = ALIGN(sizeof(new_ptr_list_t));
291 
296  &new_ptr_list,
297  &new_ptr_list,
298  0,
299  {
300 #if _DEBUG_NEW_FILENAME_LEN == 0
301  _NULLPTR
302 #else
303  ""
304 #endif
305  },
306  0,
307  0,
308 #if _DEBUG_NEW_REMEMBER_STACK_TRACE
309  _NULLPTR,
310 #endif
312 };
313 
318 
323 
327 static size_t total_mem_alloc = 0;
328 
333 bool new_autocheck_flag = true;
334 
338 bool new_verbose_flag = false;
339 
345 FILE* new_output_fp = stderr;
346 
356 
363 
369 
370 #if _DEBUG_NEW_USE_ADDR2LINE
380 static bool print_position_from_addr(const void* addr)
381 {
382  static const void* last_addr = _NULLPTR;
383  static char last_info[256] = "";
384  if (addr == last_addr)
385  {
386  if (last_info[0] == '\0')
387  return false;
388  fprintf(new_output_fp, "%s", last_info);
389  return true;
390  }
391  if (new_progname)
392  {
393 #if NVWA_APPLE
394  const char addr2line_cmd[] = "atos -o ";
395 #else
396  const char addr2line_cmd[] = "addr2line -e ";
397 #endif
398 
399 #if NVWA_WINDOWS
400  const int exeext_len = 4;
401 #else
402  const int exeext_len = 0;
403 #endif
404 
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";
410 #else
411  const char ignore_err[] = "";
412 #endif
413  char* cmd = (char*)alloca(strlen(new_progname)
414  + exeext_len
415  + sizeof addr2line_cmd - 1
416  + sizeof ignore_err - 1
417  + sizeof(void*) * 2
418  + 4 /* SP + "0x" + null */);
419  strcpy(cmd, addr2line_cmd);
420  strcpy(cmd + sizeof addr2line_cmd - 1, new_progname);
421  size_t len = strlen(cmd);
422 #if NVWA_WINDOWS
423  if (len <= 4
424  || (strcmp(cmd + len - 4, ".exe") != 0 &&
425  strcmp(cmd + len - 4, ".EXE") != 0))
426  {
427  strcpy(cmd + len, ".exe");
428  len += 4;
429  }
430 #endif
431  sprintf(cmd + len, " %p%s", addr, ignore_err);
432  FILE* fp = popen(cmd, "r");
433  if (fp)
434  {
435  char buffer[sizeof last_info] = "";
436  len = 0;
437  if (fgets(buffer, sizeof buffer, fp))
438  {
439  len = strlen(buffer);
440  if (buffer[len - 1] == '\n')
441  buffer[--len] = '\0';
442  }
443  int res = pclose(fp);
444  // Display the file/line information only if the command
445  // is executed successfully and the output points to a
446  // valid position, but the result will be cached if only
447  // the command is executed successfully.
448  if (res == 0 && len > 0)
449  {
450  last_addr = addr;
451  if (buffer[len - 1] == '0' && buffer[len - 2] == ':')
452  last_info[0] = '\0';
453  else
454  {
455  fprintf(new_output_fp, "%s", buffer);
456  strcpy(last_info, buffer);
457  return true;
458  }
459  }
460  }
461  }
462  return false;
463 }
464 #else
471 static bool print_position_from_addr(const void*)
472 {
473  return false;
474 }
475 #endif // _DEBUG_NEW_USE_ADDR2LINE
476 
488 static void print_position(const void* ptr, int line)
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 }
504 
505 #if _DEBUG_NEW_REMEMBER_STACK_TRACE
517 static void print_stacktrace(void** stacktrace)
518 {
520  {
521  fprintf(new_output_fp, "Stack backtrace:\n");
522  for (size_t i = 0; stacktrace[i] != _NULLPTR; ++i)
523  fprintf(new_output_fp, "%p\n", stacktrace[i]);
524  }
525  else
526  {
528  }
529 }
530 #endif
531 
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 }
556 
557 #if _DEBUG_NEW_TAILCHECK
566 static bool check_tail(new_ptr_list_t* ptr)
567 {
568  const unsigned char* const tail_ptr = (unsigned char*)ptr +
570  for (int i = 0; i < _DEBUG_NEW_TAILCHECK; ++i)
571  if (tail_ptr[i] != _DEBUG_NEW_TAILCHECK_CHAR)
572  return false;
573  return true;
574 }
575 #endif
576 
587 static void* alloc_mem(size_t size, const char* file, int line, bool is_array)
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 }
682 
691 static void free_pointer(void* usr_ptr, void* addr, bool is_array)
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 }
763 
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 }
837 
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 }
896 
905 {
906  if (usr_ptr == _NULLPTR)
907  return;
908 
909  // In an expression `new NonPODType[size]', the pointer returned is
910  // not the pointer returned by operator new[], but offset by size_t
911  // to leave room for the size. It needs to be compensated here.
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) {
917  fprintf(new_output_fp,
918  "warning: memory unaligned; skipping processing (%s:%d)\n",
919  _M_file, _M_line);
920  return;
921  }
922  usr_ptr = (char*)usr_ptr - sizeof(size_t);
923  }
924 
925  new_ptr_list_t* ptr =
926  (new_ptr_list_t*)((char*)usr_ptr - ALIGNED_LIST_ITEM_SIZE);
927  if (ptr->magic != DEBUG_NEW_MAGIC || ptr->line != 0)
928  {
930  fprintf(new_output_fp,
931  "warning: debug_new used with placement new (%s:%d)\n",
932  _M_file, _M_line);
933  return;
934  }
935  if (new_verbose_flag) {
937  fprintf(new_output_fp,
938  "info: pointer %p allocated from %s:%d\n",
939  usr_ptr, _M_file, _M_line);
940  }
941 #if _DEBUG_NEW_FILENAME_LEN == 0
942  ptr->file = _M_file;
943 #else
944  strncpy(ptr->file, _M_file, _DEBUG_NEW_FILENAME_LEN - 1)
945  [_DEBUG_NEW_FILENAME_LEN - 1] = '\0';
946 #endif
947  ptr->line = _M_line;
948 #if _DEBUG_NEW_REMEMBER_STACK_TRACE == 2
949  free(ptr->stacktrace);
950  ptr->stacktrace = _NULLPTR;
951 #endif
952 }
953 
958 
963 {
964  ++_S_count;
965 }
966 
972 {
973  if (--_S_count == 0 && new_autocheck_flag)
974  if (check_leaks())
975  {
976  new_verbose_flag = true;
977 #if defined(__GNUC__) && __GNUC__ == 3
978  if (!getenv("GLIBCPP_FORCE_NEW") && !getenv("GLIBCXX_FORCE_NEW"))
979  fprintf(new_output_fp,
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");
983 #endif
984  }
985 }
986 
988 
989 #if NVWA_USE_NAMESPACE
990 using namespace nvwa;
991 #endif // NVWA_USE_NAMESPACE
992 
1003 void* operator new(size_t size, const char* file, int line)
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 }
1015 
1026 void* operator new[](size_t size, const char* file, int line)
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 }
1038 
1047 void* operator new(size_t size)
1048 {
1049  return operator new(size, (char*)_DEBUG_NEW_CALLER_ADDRESS, 0);
1050 }
1051 
1060 void* operator new[](size_t size)
1061 {
1062  return operator new[](size, (char*)_DEBUG_NEW_CALLER_ADDRESS, 0);
1063 }
1064 
1072 void* operator new(size_t size, const std::nothrow_t&) _NOEXCEPT
1073 {
1074  return alloc_mem(size, (char*)_DEBUG_NEW_CALLER_ADDRESS, 0, false);
1075 }
1076 
1084 void* operator new[](size_t size, const std::nothrow_t&) _NOEXCEPT
1085 {
1086  return alloc_mem(size, (char*)_DEBUG_NEW_CALLER_ADDRESS, 0, true);
1087 }
1088 
1094 void operator delete(void* ptr) _NOEXCEPT
1095 {
1097 }
1098 
1104 void operator delete[](void* ptr) _NOEXCEPT
1105 {
1107 }
1108 
1109 #if __cplusplus >= 201402L
1110 // GCC under C++14 wants these definitions
1111 
1112 void operator delete(void* ptr, size_t) _NOEXCEPT
1113 {
1115 }
1116 
1117 void operator delete[](void* ptr, size_t) _NOEXCEPT
1118 {
1120 }
1121 #endif
1122 
1134 void operator delete(void* ptr, const char* file, int line) _NOEXCEPT
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 }
1147 
1156 void operator delete[](void* ptr, const char* file, int line) _NOEXCEPT
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 }
1169 
1176 void operator delete(void* ptr, const std::nothrow_t&) _NOEXCEPT
1177 {
1178  operator delete(ptr, (char*)_DEBUG_NEW_CALLER_ADDRESS, 0);
1179 }
1180 
1187 void operator delete[](void* ptr, const std::nothrow_t&) _NOEXCEPT
1188 {
1189  operator delete[](ptr, (char*)_DEBUG_NEW_CALLER_ADDRESS, 0);
1190 }
1191 
1192 // This is to make Doxygen happy
1193 #undef _DEBUG_NEW_REMEMBER_STACK_TRACE
1194 //#define _DEBUG_NEW_REMEMBER_STACK_TRACE 0
1195 
1196 PRAGMA45(GCC diagnostic pop)
1197 PRAGMACLANG6GCC(GCC diagnostic pop)
#define NVWA_NAMESPACE_BEGIN
Definition: _nvwa.h:59
#define NVWA_NAMESPACE_END
Definition: _nvwa.h:60
#define _NULLPTR
Definition: c++11.h:327
static int _S_count
Definition: debug_new.h:197
const char * _M_file
Definition: debug_new.h:166
const int _M_line
Definition: debug_new.h:167
void _M_process(void *ptr)
Definition: debug_new.cpp:904
bool new_autocheck_flag
Definition: debug_new.cpp:333
static void * alloc_mem(size_t size, const char *file, int line, bool is_array)
Definition: debug_new.cpp:587
static void print_position(const void *ptr, int line)
Definition: debug_new.cpp:488
static bool is_leak_whitelisted(new_ptr_list_t *ptr)
Definition: debug_new.cpp:540
#define _DEBUG_NEW_ERROR_ACTION
#define _DEBUG_NEW_PROGNAME
#define _DEBUG_NEW_TAILCHECK
static size_t total_mem_alloc
Definition: debug_new.cpp:327
const char * new_progname
Definition: debug_new.cpp:355
#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 bool print_position_from_addr(const void *)
Definition: debug_new.cpp:471
static void free_pointer(void *usr_ptr, void *addr, bool is_array)
Definition: debug_new.cpp:691
static new_ptr_list_t new_ptr_list
Definition: debug_new.cpp:295
int check_leaks()
Definition: debug_new.cpp:769
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
#define ALIGN(s)
#define _DEBUG_NEW_CALLER_ADDRESS
leak_whitelist_callback_t leak_whitelist_callback
Definition: debug_new.cpp:368
int check_mem_corruption()
Definition: debug_new.cpp:844
stacktrace_print_callback_t stacktrace_print_callback
Definition: debug_new.cpp:362
bool(* leak_whitelist_callback_t)(char const *file, int line, void *addr, void **stacktrace)
Definition: debug_new.h:117
void(* stacktrace_print_callback_t)(FILE *fp, void **stacktrace)
Definition: debug_new.h:102
PRAGMA45(GCC diagnostic push) PRAGMA45(GCC diagnostic ignored "-Wredundant-decls") PRAGMA45(GCC diagnostic pop) class TestMain
#define PRAGMACLANG6GCC(str)
Definition: localconsts.h:240
#define _NOEXCEPT
Definition: msemstdvector.h:26
bool msg(InputEvent &event)
Definition: chat.cpp:39
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