debug_new.cc Source File

Back to the index.

debug_new.cc
Go to the documentation of this file.
1 #include <iostream>
2 
3 /*
4  * GXemul specific changes to debug_new.cc:
5  *
6  * x) debug_new.cpp renamed debug_new.cc.
7  * x) #include <alloca.h> commented out.
8  * x) (unsigned) added in some places to get rid of warnings.
9  * x) a brief Doxygen section added to struct new_ptr_list_t's
10  * comment
11  * x) #print_position changed to print_position (removed the #), to
12  * suppress a Doxygen warning
13  * x) "@file" changed to "@ file" to suppress a Doxygen warning.
14  * x) variable names in local scopes changed to allow usage of GCC's -Wshadow
15  * x) a "catch point" added for catching specific (repeatable) allocations
16  */
17 
18 #ifndef NDEBUG
19 
20 // -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
21 // vim:tabstop=4:shiftwidth=4:expandtab:
22 
23 /*
24  * Copyright (C) 2004-2005 Wu Yongwei <adah at users dot sourceforge dot net>
25  *
26  * This software is provided 'as-is', without any express or implied
27  * warranty. In no event will the authors be held liable for any
28  * damages arising from the use of this software.
29  *
30  * Permission is granted to anyone to use this software for any purpose,
31  * including commercial applications, and to alter it and redistribute
32  * it freely, subject to the following restrictions:
33  *
34  * 1. The origin of this software must not be misrepresented; you must
35  * not claim that you wrote the original software. If you use this
36  * software in a product, an acknowledgment in the product
37  * documentation would be appreciated but is not required.
38  * 2. Altered source versions must be plainly marked as such, and must
39  * not be misrepresented as being the original software.
40  * 3. This notice may not be removed or altered from any source
41  * distribution.
42  *
43  * This file is part of Stones of Nvwa:
44  * http://sourceforge.net/projects/nvwa
45  *
46  */
47 
48 /**
49  * @ file debug_new.cpp
50  *
51  * Implementation of debug versions of new and delete to check leakage.
52  *
53  * @version 3.16, 2005/11/22
54  * @author Wu Yongwei
55  *
56  */
57 
58 #include <new>
59 #include <assert.h>
60 #include <limits.h>
61 #include <stdio.h>
62 #include <stdlib.h>
63 #include <string.h>
64 #ifdef __unix__
65 // #include <alloca.h>
66 #endif
67 #ifdef _WIN32
68 #include <malloc.h>
69 #endif
70 #include "thirdparty/fast_mutex.h"
72 
73 #if !_FAST_MUTEX_CHECK_INITIALIZATION && !defined(_NOTHREADS)
74 #error "_FAST_MUTEX_CHECK_INITIALIZATION not set: check_leaks may not work"
75 #endif
76 
77 /**
78  * @def _DEBUG_NEW_ALIGNMENT
79  *
80  * The alignment requirement of allocated memory blocks. It must be a
81  * power of two.
82  */
83 #ifndef _DEBUG_NEW_ALIGNMENT
84 #define _DEBUG_NEW_ALIGNMENT 16
85 #endif
86 
87 /**
88  * @def _DEBUG_NEW_CALLER_ADDRESS
89  *
90  * The expression to return the caller address. print_position will
91  * later on use this address to print the position information of memory
92  * operation points.
93  */
94 #ifndef _DEBUG_NEW_CALLER_ADDRESS
95 #ifdef __GNUC__
96 #define _DEBUG_NEW_CALLER_ADDRESS __builtin_return_address(0)
97 #else
98 #define _DEBUG_NEW_CALLER_ADDRESS NULL
99 #endif
100 #endif
101 
102 /**
103  * @def _DEBUG_NEW_ERROR_ACTION
104  *
105  * The action to take when an error occurs. The default behaviour is to
106  * call \e abort, unless \c _DEBUG_NEW_ERROR_CRASH is defined, in which
107  * case a segmentation fault will be triggered instead (which can be
108  * useful on platforms like Windows that do not generate a core dump
109  * when \e abort is called).
110  */
111 #ifndef _DEBUG_NEW_ERROR_ACTION
112 #ifndef _DEBUG_NEW_ERROR_CRASH
113 #define _DEBUG_NEW_ERROR_ACTION abort()
114 #else
115 #define _DEBUG_NEW_ERROR_ACTION do { *((char*)0) = 0; abort(); } while (0)
116 #endif
117 #endif
118 
119 /**
120  * @def _DEBUG_NEW_FILENAME_LEN
121  *
122  * The length of file name stored if greater than zero. If it is zero,
123  * only a const char pointer will be stored. Currently the default
124  * behaviour is to copy the file name, because I found that the exit
125  * leakage check cannot access the address of the file name sometimes
126  * (in my case, a core dump will occur when trying to access the file
127  * name in a shared library after a \c SIGINT). If the default value is
128  * too small for you, try defining it to \c 52, which makes the size of
129  * new_ptr_list_t 64 (it is 32 by default) on 32-bit platforms.
130  */
131 #ifndef _DEBUG_NEW_FILENAME_LEN
132 #define _DEBUG_NEW_FILENAME_LEN 20
133 #endif
134 
135 /**
136  * @def _DEBUG_NEW_HASHTABLESIZE
137  *
138  * The size of the hash bucket for the table to store pointers to
139  * allocated memory. To ensure good performance, always make it a power
140  * of two.
141  */
142 #ifndef _DEBUG_NEW_HASHTABLESIZE
143 #define _DEBUG_NEW_HASHTABLESIZE 16384
144 #endif
145 
146 /**
147  * @def _DEBUG_NEW_HASH
148  *
149  * The hash function for the pointers. This one has good performance in
150  * test for me.
151  */
152 #ifndef _DEBUG_NEW_HASH
153 #define _DEBUG_NEW_HASH(p) (((size_t)(p) >> 8) % _DEBUG_NEW_HASHTABLESIZE)
154 #endif
155 
156 /**
157  * @def _DEBUG_NEW_PROGNAME
158  *
159  * The program (executable) name to be set at compile time. It is
160  * better to assign the full program path to #new_progname in \e main
161  * (at run time) than to use this (compile-time) macro, but this macro
162  * serves well as a quick hack. Note also that double quotation marks
163  * need to be used around the program name, i.e., one should specify a
164  * command-line option like <code>-D_DEBUG_NEW_PROGNAME=\"a.out\"</code>
165  * in \e bash, or <code>-D_DEBUG_NEW_PROGNAME=\"a.exe\"</code> in the
166  * Windows command prompt.
167  */
168 #ifndef _DEBUG_NEW_PROGNAME
169 #define _DEBUG_NEW_PROGNAME NULL
170 #endif
171 
172 /**
173  * @def _DEBUG_NEW_USE_ADDR2LINE
174  *
175  * Whether to use \e addr2line to convert a caller address to file/line
176  * information. Defining it to a non-zero value will enable the
177  * conversion (automatically done if GCC is detected). Defining it to
178  * zero will disable the conversion.
179  */
180 #ifndef _DEBUG_NEW_USE_ADDR2LINE
181 #ifdef __GNUC__
182 #define _DEBUG_NEW_USE_ADDR2LINE 1
183 #else
184 #define _DEBUG_NEW_USE_ADDR2LINE 0
185 #endif
186 #endif
187 
188 #ifdef _MSC_VER
189 #pragma warning(disable: 4073) // #pragma init_seg(lib) used
190 #pragma warning(disable: 4290) // C++ exception specification ignored
191 #pragma init_seg(lib)
192 #endif
193 
194 #undef _DEBUG_NEW_EMULATE_MALLOC
195 #undef _DEBUG_NEW_REDEFINE_NEW
196 /**
197  * Macro to indicate whether redefinition of \c new is wanted. Here it
198  * is defined to \c 0 to disable the redefinition of \c new.
199  */
200 #define _DEBUG_NEW_REDEFINE_NEW 0
201 #include "thirdparty/debug_new.h"
202 
203 /**
204  * Gets the aligned value of memory block size.
205  */
206 #define align(s) \
207  (((s) + _DEBUG_NEW_ALIGNMENT - 1) & ~(_DEBUG_NEW_ALIGNMENT - 1))
208 
209 /**
210  * \brief Part of Wu Yongwei's new/delete debug
211  * memory leak detector.
212  *
213  * Structure to store the position information where \c new occurs.
214  */
216 {
218  union
219  {
220 #if _DEBUG_NEW_FILENAME_LEN == 0
221  const char* file;
222 #else
224 #endif
225  void* addr;
226  };
227  int line;
228  size_t size;
229 };
230 
231 /**
232  * The extra memory allocated by <code>operator new</code>.
233  */
235 
236 /**
237  * Array of pointer lists of a hash value.
238  */
239 static new_ptr_list_t* new_ptr_list[_DEBUG_NEW_HASHTABLESIZE];
240 
241 /**
242  * Array of mutex guards to protect simultaneous access to the pointer
243  * lists of a hash value.
244  */
245 static fast_mutex new_ptr_lock[_DEBUG_NEW_HASHTABLESIZE];
246 
247 /**
248  * The mutex guard to protect simultaneous output to #new_output_fp.
249  */
250 static fast_mutex new_output_lock;
251 
252 /**
253  * Total memory allocated in bytes.
254  */
255 static size_t total_mem_alloc = 0;
256 
257 /**
258  * Flag to control whether #check_leaks will be automatically called on
259  * program exit.
260  */
261 bool new_autocheck_flag = true;
262 
263 /**
264  * Flag to control whether verbose messages are output.
265  */
266 bool new_verbose_flag = false;
267 
268 /**
269  * Pointer to the output stream. The default output is \e stderr, and
270  * one may change it to a user stream if needed (say, #new_verbose_flag
271  * is \c true and there are a lot of (de)allocations).
272  */
273 FILE* new_output_fp = stderr;
274 
275 /**
276  * Pointer to the program name. Its initial value is the macro
277  * #_DEBUG_NEW_PROGNAME. You should try to assign the program path to
278  * it early in your application. Assigning <code>argv[0]</code> to it
279  * in \e main is one way. If you use \e bash or \e ksh (or similar),
280  * the following statement is probably what you want:
281  * `<code>new_progname = getenv("_");</code>'.
282  */
284 
285 #if _DEBUG_NEW_USE_ADDR2LINE
286 /**
287  * Tries printing the position information from an instruction address.
288  * This is the version that uses \e addr2line.
289  *
290  * @param addr the instruction address to convert and print
291  * @return \c true if the address is converted successfully (and
292  * the result is printed); \c false if no useful
293  * information is got (and nothing is printed)
294  */
295 static bool print_position_from_addr(const void* addr)
296 {
297  static const void* last_addr = NULL;
298  static char last_info[256] = "";
299  if (addr == last_addr)
300  {
301  if (last_info[0] == '\0')
302  return false;
303  fprintf(new_output_fp, "%s", last_info);
304  return true;
305  }
306  if (new_progname)
307  {
308  const char addr2line_cmd[] = "addr2line -e ";
309 #if defined(__CYGWIN__) || defined(_WIN32)
310  const int exeext_len = 4;
311 #else
312  const int exeext_len = 0;
313 #endif
314 #if !defined(__CYGWIN__) && defined(__unix__)
315  const char ignore_err[] = " 2>/dev/null";
316 #elif defined(__CYGWIN__) || \
317  (defined(_WIN32) && defined(WINVER) && WINVER >= 0x0500)
318  const char ignore_err[] = " 2>nul";
319 #else
320  const char ignore_err[] = "";
321 #endif
322  char* cmd = (char*)alloca(strlen(new_progname)
323  + exeext_len
324  + sizeof addr2line_cmd - 1
325  + sizeof ignore_err - 1
326  + sizeof(void*) * 2
327  + 4 /* SP + "0x" + null */);
328  strcpy(cmd, addr2line_cmd);
329  strcpy(cmd + sizeof addr2line_cmd - 1, new_progname);
330  size_t len = strlen(cmd);
331 #if defined(__CYGWIN__) || defined(_WIN32)
332  if (len <= 4
333  || (strcmp(cmd + len - 4, ".exe") != 0 &&
334  strcmp(cmd + len - 4, ".EXE") != 0))
335  {
336  strcpy(cmd + len, ".exe");
337  len += 4;
338  }
339 #endif
340  sprintf(cmd + len, " %p%s", addr, ignore_err);
341  FILE* fp = popen(cmd, "r");
342  if (fp)
343  {
344  char buffer[sizeof last_info] = "";
345  len = 0;
346  if (fgets(buffer, sizeof buffer, fp))
347  {
348  len = strlen(buffer);
349  if (buffer[len - 1] == '\n')
350  buffer[--len] = '\0';
351  }
352  int res = pclose(fp);
353  // Display the file/line information only if the command
354  // is executed successfully and the output points to a
355  // valid position, but the result will be cached if only
356  // the command is executed successfully.
357  if (res == 0 && len > 0)
358  {
359  last_addr = addr;
360  if (buffer[len - 1] == '0' && buffer[len - 2] == ':')
361  last_info[0] = '\0';
362  else
363  {
364  fprintf(new_output_fp, "%s", buffer);
365  strcpy(last_info, buffer);
366  return true;
367  }
368  }
369  }
370  }
371  return false;
372 }
373 #else
374 /**
375  * Tries printing the position information from an instruction address.
376  * This is the stub version that does nothing at all.
377  *
378  * @return \c false always
379  */
380 static bool print_position_from_addr(const void*)
381 {
382  return false;
383 }
384 #endif // _DEBUG_NEW_USE_ADDR2LINE
385 
386 /**
387  * Prints the position information of a memory operation point. When \c
388  * _DEBUG_NEW_USE_ADDR2LINE is defined to a non-zero value, this
389  * function will try to convert a given caller address to file/line
390  * information with \e addr2line.
391  *
392  * @param ptr source file name if \e line is non-zero; caller address
393  * otherwise
394  * @param line source line number if non-zero; indication that \e ptr
395  * is the caller address otherwise
396  */
397 static void print_position(const void* ptr, int line)
398 {
399  line &= ~INT_MIN; // Result from new[] if highest bit set: Ignore
400  if (line != 0) // Is file/line information present?
401  {
402  fprintf(new_output_fp, "%s:%d", (const char*)ptr, line);
403  }
404  else if (ptr != NULL) // Is caller address present?
405  {
406  if (!print_position_from_addr(ptr)) // Fail to get source position?
407  fprintf(new_output_fp, "%p", ptr);
408  }
409  else // No information is present
410  {
411  fprintf(new_output_fp, "<Unknown>");
412  }
413 }
414 
415 /**
416  * Searches for the raw pointer given a user pointer. The term `raw
417  * pointer' here refers to the pointer to the pointer to originally
418  * <em>malloc</em>'d memory.
419  *
420  * @param pointer user pointer to search for
421  * @param hash_index hash index of the user pointer
422  * @return the raw pointer if searching is successful; or
423  * \c NULL otherwise
424  */
425 static new_ptr_list_t** search_pointer(void* pointer, size_t hash_index)
426 {
427  new_ptr_list_t** raw_ptr = &new_ptr_list[hash_index];
428  while (*raw_ptr)
429  {
430  if ((char*)*raw_ptr + aligned_list_item_size == pointer)
431  {
432  return raw_ptr;
433  }
434  raw_ptr = &(*raw_ptr)->next;
435  }
436  return NULL;
437 }
438 
439 /**
440  * Frees memory and adjusts pointers relating to a raw pointer. If the
441  * highest bit of \c line (set from a previous <code>new[]</code> call)
442  * does not agree with \c array_mode, program will abort with an error
443  * message.
444  *
445  * @param raw_ptr raw pointer to free
446  * @param addr pointer to the caller
447  * @param array_mode flag indicating whether it is invoked by a
448  * <code>delete[]</code> call
449  */
450 static void free_pointer(new_ptr_list_t** raw_ptr, void* addr, bool array_mode)
451 {
452  new_ptr_list_t* ptr = *raw_ptr;
453  int array_mode_mismatch = array_mode ^ ((ptr->line & INT_MIN) != 0);
454  if (array_mode_mismatch)
455  {
456  const char* msg;
457  if (array_mode)
458  msg = "delete[] after new";
459  else
460  msg = "delete after new[]";
461  fast_mutex_autolock lock(new_output_lock);
462  fprintf(new_output_fp,
463  "%s: pointer %p (size %u)\n\tat ",
464  msg,
465  (char*)ptr + aligned_list_item_size,
466  (unsigned) ptr->size);
467  print_position(addr, 0);
468  fprintf(new_output_fp, "\n\toriginally allocated at ");
469  if ((ptr->line & ~INT_MIN) != 0)
470  print_position(ptr->file, ptr->line);
471  else
472  print_position(ptr->addr, ptr->line);
473  fprintf(new_output_fp, "\n");
474  fflush(new_output_fp);
476  }
477  total_mem_alloc -= ptr->size;
478  if (new_verbose_flag)
479  {
480  fast_mutex_autolock lock(new_output_lock);
481  fprintf(new_output_fp,
482  "delete: freeing %p (size %u, %u bytes still allocated)\n",
483  (char*)ptr + aligned_list_item_size,
484  (unsigned) ptr->size, (unsigned) total_mem_alloc);
485  }
486  *raw_ptr = ptr->next;
487  memset(ptr, 0xdd, ptr->size + aligned_list_item_size);
488  free(ptr);
489  return;
490 }
491 
492 /**
493  * Checks for memory leaks.
494  *
495  * @return zero if no leakage is found; the number of leaks otherwise
496  */
498 {
499  int leak_cnt = 0;
500  for (int i = 0; i < _DEBUG_NEW_HASHTABLESIZE; ++i)
501  {
502  fast_mutex_autolock lock(new_ptr_lock[i]);
503  new_ptr_list_t* ptr = new_ptr_list[i];
504  if (ptr == NULL)
505  continue;
506  while (ptr)
507  {
508  fast_mutex_autolock lock2(new_output_lock);
509  fprintf(new_output_fp,
510  "Leaked object at %p (size %u, ",
511  (char*)ptr + aligned_list_item_size,
512  (unsigned) ptr->size);
513  if ((ptr->line & ~INT_MIN) != 0)
514  print_position(ptr->file, ptr->line);
515  else
516  print_position(ptr->addr, ptr->line);
517  fprintf(new_output_fp, ")\n");
518  ptr = ptr->next;
519  ++leak_cnt;
520  }
521  }
522  return leak_cnt;
523 }
524 
525 void* operator new(size_t size, const char* file, int line)
526 {
527  assert((line & INT_MIN) == 0);
529  Alignment_must_be_power_of_two);
530  size_t s = size + aligned_list_item_size;
531  new_ptr_list_t* ptr = (new_ptr_list_t*)malloc(s);
532  if (ptr == NULL)
533  {
534  fast_mutex_autolock lock(new_output_lock);
535  fprintf(new_output_fp,
536  "new: out of memory when allocating %u bytes\n",
537  (unsigned) size);
538  fflush(new_output_fp);
540  }
541  void* pointer = (char*)ptr + aligned_list_item_size;
542 
543  // GXemul hack/addition: Crash on a specific allocation. Useful
544  // for getting a call stack for a memory leak, at the point where the
545  // actual allocation took place. (Only possible if the address is
546  // stable over multiple runs.)
547  if ((size_t)pointer == 0xfefefefecdcdcdcdULL)
548  {
549  static int counter = 0;
550  counter ++;
551  std::cerr << "--> MEMORY LEAK CATCH POINT, counter = " << counter << "\n";
552 
553  if (counter == -42)
554  {
555  abort();
556  }
557  }
558 
559  size_t hash_index = _DEBUG_NEW_HASH(pointer);
560 #if _DEBUG_NEW_FILENAME_LEN == 0
561  ptr->file = file;
562 #else
563  if (line)
564  strncpy(ptr->file, file, _DEBUG_NEW_FILENAME_LEN - 1)
565  [_DEBUG_NEW_FILENAME_LEN - 1] = '\0';
566  else
567  ptr->addr = (void*)file;
568 #endif
569  ptr->line = line;
570  ptr->size = size;
571  {
572  fast_mutex_autolock lock(new_ptr_lock[hash_index]);
573  ptr->next = new_ptr_list[hash_index];
574  new_ptr_list[hash_index] = ptr;
575  }
576  if (new_verbose_flag)
577  {
578  fast_mutex_autolock lock(new_output_lock);
579  fprintf(new_output_fp,
580  "new: allocated %p (size %u, ",
581  pointer, (unsigned) size);
582  if (line != 0)
583  print_position(ptr->file, ptr->line);
584  else
585  print_position(ptr->addr, ptr->line);
586  fprintf(new_output_fp, ")\n");
587  }
588  total_mem_alloc += size;
589  return pointer;
590 }
591 
592 void* operator new[](size_t size, const char* file, int line)
593 {
594  void* pointer = operator new(size, file, line);
595  new_ptr_list_t* ptr =
596  (new_ptr_list_t*)((char*)pointer - aligned_list_item_size);
597  assert((ptr->line & INT_MIN) == 0);
598  ptr->line |= INT_MIN; // Result from new[] if highest bit set: Set
599  return pointer;
600 }
601 
602 void* operator new(size_t size) throw(std::bad_alloc)
603 {
604  return operator new(size, (char*)_DEBUG_NEW_CALLER_ADDRESS, 0);
605 }
606 
607 void* operator new[](size_t size) throw(std::bad_alloc)
608 {
609  return operator new[](size, (char*)_DEBUG_NEW_CALLER_ADDRESS, 0);
610 }
611 
612 #if !defined(__BORLANDC__) || __BORLANDC__ > 0x551
613 void* operator new(size_t size, const std::nothrow_t&) throw()
614 {
615  return operator new(size, (char*)_DEBUG_NEW_CALLER_ADDRESS, 0);
616 }
617 
618 void* operator new[](size_t size, const std::nothrow_t&) throw()
619 {
620  return operator new[](size, (char*)_DEBUG_NEW_CALLER_ADDRESS, 0);
621 }
622 #endif
623 
624 void operator delete(void* pointer) throw()
625 {
626  if (pointer == NULL)
627  return;
628  size_t hash_index = _DEBUG_NEW_HASH(pointer);
629  fast_mutex_autolock lock(new_ptr_lock[hash_index]);
630  new_ptr_list_t** raw_ptr = search_pointer(pointer, hash_index);
631  if (raw_ptr == NULL)
632  {
633  fast_mutex_autolock lock2(new_output_lock);
634  fprintf(new_output_fp, "delete: invalid pointer %p at ", pointer);
635  print_position(_DEBUG_NEW_CALLER_ADDRESS, 0);
636  fprintf(new_output_fp, "\n");
637  fflush(new_output_fp);
639  }
640  free_pointer(raw_ptr, _DEBUG_NEW_CALLER_ADDRESS, false);
641 }
642 
643 void operator delete[](void* pointer) throw()
644 {
645  if (pointer == NULL)
646  return;
647  size_t hash_index = _DEBUG_NEW_HASH(pointer);
648  fast_mutex_autolock lock(new_ptr_lock[hash_index]);
649  new_ptr_list_t** raw_ptr = search_pointer(pointer, hash_index);
650  if (raw_ptr == NULL)
651  {
652  fast_mutex_autolock lock2(new_output_lock);
653  fprintf(new_output_fp, "delete[]: invalid pointer %p at ", pointer);
654  print_position(_DEBUG_NEW_CALLER_ADDRESS, 0);
655  fprintf(new_output_fp, "\n");
656  fflush(new_output_fp);
658  }
659  free_pointer(raw_ptr, _DEBUG_NEW_CALLER_ADDRESS, true);
660 }
661 
662 #if HAS_PLACEMENT_DELETE
663 void operator delete(void* pointer, const char* file, int line) throw()
664 {
665  if (new_verbose_flag)
666  {
667  fast_mutex_autolock lock(new_output_lock);
668  fprintf(new_output_fp,
669  "info: exception thrown on initializing object at %p (",
670  pointer);
671  print_position(file, line);
672  fprintf(new_output_fp, ")\n");
673  }
674  operator delete(pointer);
675 }
676 
677 void operator delete[](void* pointer, const char* file, int line) throw()
678 {
679  if (new_verbose_flag)
680  {
681  fast_mutex_autolock lock(new_output_lock);
682  fprintf(new_output_fp,
683  "info: exception thrown on initializing objects at %p (",
684  pointer);
685  print_position(file, line);
686  fprintf(new_output_fp, ")\n");
687  }
688  operator delete[](pointer);
689 }
690 
691 void operator delete(void* pointer, const std::nothrow_t&) throw()
692 {
693  operator delete(pointer, (char*)_DEBUG_NEW_CALLER_ADDRESS, 0);
694 }
695 
696 void operator delete[](void* pointer, const std::nothrow_t&) throw()
697 {
698  operator delete[](pointer, (char*)_DEBUG_NEW_CALLER_ADDRESS, 0);
699 }
700 #endif // HAS_PLACEMENT_DELETE
701 
702 int __debug_new_counter::_count = 0;
703 
704 /**
705  * Constructor to increment the count.
706  */
708 {
709  ++_count;
710 }
711 
712 /**
713  * Destructor to decrement the count. When the count is zero,
714  * #check_leaks will be called.
715  */
717 {
718  if (--_count == 0 && new_autocheck_flag)
719  if (check_leaks())
720  {
721  new_verbose_flag = true;
722 #if defined(__GNUC__) && __GNUC__ >= 3
723  if (!getenv("GLIBCPP_FORCE_NEW") && !getenv("GLIBCXX_FORCE_NEW"))
724  fprintf(new_output_fp,
725 "*** WARNING: GCC 3 or later is detected, please make sure the\n"
726 " environment variable GLIBCPP_FORCE_NEW (GCC 3.2 and 3.3) or\n"
727 " GLIBCXX_FORCE_NEW (GCC 3.4 and later) is defined. Check the\n"
728 " README file for details.\n");
729 #endif
730  }
731 }
732 
733 #endif // NDEBUG
_DEBUG_NEW_FILENAME_LEN
#define _DEBUG_NEW_FILENAME_LEN
Definition: debug_new.cc:132
_DEBUG_NEW_HASHTABLESIZE
#define _DEBUG_NEW_HASHTABLESIZE
Definition: debug_new.cc:143
static_assert.h
__debug_new_counter::~__debug_new_counter
~__debug_new_counter()
Definition: debug_new.cc:716
new_ptr_list_t::size
size_t size
Definition: debug_new.cc:228
_DEBUG_NEW_ALIGNMENT
#define _DEBUG_NEW_ALIGNMENT
Definition: debug_new.cc:84
new_ptr_list_t::line
int line
Definition: debug_new.cc:227
align
#define align(s)
Definition: debug_new.cc:206
check_leaks
int check_leaks()
Definition: debug_new.cc:497
new_ptr_list_t::next
new_ptr_list_t * next
Definition: debug_new.cc:217
addr
uint32_t addr
Definition: tmp_arm_multi.cc:52
cmd
Definition: debugger_cmds.cc:1189
aligned_list_item_size
const int aligned_list_item_size
Definition: debug_new.cc:234
STATIC_ASSERT
#define STATIC_ASSERT(_Expr, _Msg)
Definition: static_assert.h:55
strlen
void COMBINE() strlen(struct cpu *cpu, struct arm_instr_call *ic, int low_addr)
Definition: cpu_arm_instr.cc:2333
new_ptr_list_t
Part of Wu Yongwei's new/delete debug memory leak detector.
Definition: debug_new.cc:215
_DEBUG_NEW_CALLER_ADDRESS
#define _DEBUG_NEW_CALLER_ADDRESS
Definition: debug_new.cc:98
fast_mutex_autolock
Part of Wu Yongwei's new/delete debug memory leak detector.
Definition: fast_mutex.h:315
new_output_fp
FILE * new_output_fp
Definition: debug_new.cc:273
new_progname
const char * new_progname
Definition: debug_new.cc:283
_DEBUG_NEW_ERROR_ACTION
#define _DEBUG_NEW_ERROR_ACTION
Definition: debug_new.cc:113
new_autocheck_flag
bool new_autocheck_flag
Definition: debug_new.cc:261
debug_new.h
fast_mutex.h
_DEBUG_NEW_PROGNAME
#define _DEBUG_NEW_PROGNAME
Definition: debug_new.cc:169
__debug_new_counter::__debug_new_counter
__debug_new_counter()
Definition: debug_new.cc:707
fast_mutex
Part of Wu Yongwei's new/delete debug memory leak detector.
Definition: fast_mutex.h:273
_DEBUG_NEW_HASH
#define _DEBUG_NEW_HASH(p)
Definition: debug_new.cc:153
new_verbose_flag
bool new_verbose_flag
Definition: debug_new.cc:266
new_ptr_list_t::file
char file[_DEBUG_NEW_FILENAME_LEN]
Definition: debug_new.cc:223
new_ptr_list_t::addr
void * addr
Definition: debug_new.cc:225

Generated on Tue Mar 24 2020 14:04:48 for GXemul by doxygen 1.8.17