diff options
Diffstat (limited to 'src/debug/debug_new.h')
-rw-r--r-- | src/debug/debug_new.h | 191 |
1 files changed, 107 insertions, 84 deletions
diff --git a/src/debug/debug_new.h b/src/debug/debug_new.h index e4e78c003..926de99de 100644 --- a/src/debug/debug_new.h +++ b/src/debug/debug_new.h @@ -2,7 +2,7 @@ // vim:tabstop=4:shiftwidth=4:expandtab: /* - * Copyright (C) 2004-2008 Wu Yongwei <adah at users dot sourceforge dot net> + * Copyright (C) 2004-2015 Wu Yongwei <adah at users dot sourceforge dot net> * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any @@ -24,50 +24,40 @@ * This file is part of Stones of Nvwa: * http://sourceforge.net/projects/nvwa * - * original version changed for ManaPlus - * - * Copyright (C) 2011-2017 The ManaPlus Developers */ /** - * @file debug_new.h + * @file debug_new.h * * Header file for checking leaks caused by unmatched new/delete. * - * @version 4.4, 2007/12/31 - * @author Wu Yongwei - * + * @date 2015-10-25 */ -#ifndef M_DEBUG_NEW_H -#define M_DEBUG_NEW_H +#ifndef NVWA_DEBUG_NEW_H +#define NVWA_DEBUG_NEW_H -#include <new> -#include <cstdio> +#include <new> // size_t/std::bad_alloc +#include <stdio.h> // FILE +#include "debug/_nvwa.h" // NVWA_NAMESPACE_* +#include "debug/c++11.h" // _NOEXCEPT -/** - * @def HAVE_PLACEMENT_DELETE - * - * Macro to indicate whether placement delete operators are supported on - * a certain compiler. Some compilers, like Borland C++ Compiler 5.5.1 - * and Digital Mars Compiler 8.42, do not support them, and the user - * must define this macro to \c 0 to make the program compile. Also - * note that in that case memory leakage will occur if an exception is - * thrown in the initialization (constructor) of a dynamically created - * object. - */ -#ifndef HAVE_PLACEMENT_DELETE -#define HAVE_PLACEMENT_DELETE 1 -#endif +/* Special allocation/deallocation functions in the global scope */ +void* operator new(size_t size, const char* file, int line); +void* operator new[](size_t size, const char* file, int line); +void operator delete(void* ptr, const char* file, int line) _NOEXCEPT; +void operator delete[](void* ptr, const char* file, int line) _NOEXCEPT; + +NVWA_NAMESPACE_BEGIN /** - * @def M_DEBUG_NEW_REDEFINE_NEW + * @def _DEBUG_NEW_REDEFINE_NEW * * Macro to indicate whether redefinition of \c new is wanted. If one - * wants to define one's own <code>operator new</code>, to call - * <code>operator new</code> directly, or to call placement \c new, it - * should be defined to \c 0 to alter the default behaviour. Unless, of - * course, one is willing to take the trouble to write something like: + * wants to define one's own <code>operator new</code>, or to call + * <code>operator new</code> directly, it should be defined to \c 0 to + * alter the default behaviour. Unless, of course, one is willing to + * take the trouble to write something like: * @code * # ifdef new * # define _NEW_REDEFINED @@ -84,47 +74,79 @@ * # endif * @endcode */ -#ifndef M_DEBUG_NEW_REDEFINE_NEW -#define M_DEBUG_NEW_REDEFINE_NEW 1 +#ifndef _DEBUG_NEW_REDEFINE_NEW +#define _DEBUG_NEW_REDEFINE_NEW 1 +#endif + +/** + * @def _DEBUG_NEW_TYPE + * + * Macro to indicate which variant of #DEBUG_NEW is wanted. The + * default value \c 1 allows the use of placement new (like + * <code>%new(std::nothrow)</code>), but the verbose output (when + * nvwa#new_verbose_flag is \c true) looks worse than some older + * versions (no file/line information for allocations). Define it + * to \c 2 to revert to the old behaviour that records file and line + * information directly on the call to <code>operator new</code>. + */ +#ifndef _DEBUG_NEW_TYPE +#define _DEBUG_NEW_TYPE 1 #endif +/** + * Callback type for stack trace printing. + * + * @param fp pointer to the output stream + * @param stacktrace pointer to the stack trace array (null-terminated) + */ +typedef void (*stacktrace_print_callback_t)(FILE* fp, void** stacktrace); + +/** + * Callback type for the leak whitelist function. \a file, \a address, + * and \a backtrace might be null depending on library configuration, + * platform, and amount of runtime information available. \a line can + * be 0 when line number info is not available at runtime. + * + * @param file null-terminated string of the file name + * @param line line number + * @param addr address of code where leakage happens + * @param stacktrace pointer to the stack trace array (null-terminated) + * @return \c true if the leak should be whitelisted; + * \c false otherwise + */ +typedef bool (*leak_whitelist_callback_t)(char const* file, int line, + void* addr, void** stacktrace); + /* Prototypes */ 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); -#if HAVE_PLACEMENT_DELETE -void operator delete(void* pointer, const char* file, int line) throw(); -void operator delete[](void* pointer, const char* file, int line) throw(); -#endif -#if defined(_MSC_VER) && _MSC_VER < 1300 -// MSVC 6 requires the following declarations; or the non-placement -// new[]/delete[] will not compile. -void* operator new[](size_t) throw(std::bad_alloc); -void operator delete[](void*) throw(); -#endif /* Control variables */ -extern bool new_autocheck_flag; // default to true: call check_leaks() on exit -extern bool new_verbose_flag; // default to false: no verbose information -extern FILE* new_output_fp; // default to stderr: output to console -extern const char* new_progname; // default to NULL; should be - // assigned argv[0] +extern bool new_autocheck_flag; // default to true: call check_leaks() on exit +extern bool new_verbose_flag; // default to false: no verbose information +extern FILE* new_output_fp; // default to stderr: output to console +extern const char* new_progname;// default to null; should be assigned argv[0] +extern stacktrace_print_callback_t stacktrace_print_callback;// default to null +extern leak_whitelist_callback_t leak_whitelist_callback; // default to null /** * @def DEBUG_NEW * * Macro to catch file/line information on allocation. If - * #M_DEBUG_NEW_REDEFINE_NEW is \c 0, one can use this macro directly; + * #_DEBUG_NEW_REDEFINE_NEW is \c 0, one can use this macro directly; * otherwise \c new will be defined to it, and one must use \c new * instead. */ -#define DEBUG_NEW __debug_new_recorder(__FILE__, __LINE__) ->* new +# if _DEBUG_NEW_TYPE == 1 +# define DEBUG_NEW NVWA::debug_new_recorder(__FILE__, __LINE__) ->* new +# else +# define DEBUG_NEW new(__FILE__, __LINE__) +# endif -# if M_DEBUG_NEW_REDEFINE_NEW +# if _DEBUG_NEW_REDEFINE_NEW # define new DEBUG_NEW # endif -# ifdef M_DEBUG_NEW_EMULATE_MALLOC +# ifdef _DEBUG_NEW_EMULATE_MALLOC # include <stdlib.h> # ifdef new # define malloc(s) ((void*)(new char[s])) @@ -132,7 +154,6 @@ extern const char* new_progname; // default to NULL; should be # define malloc(s) ((void*)(DEBUG_NEW char[s])) # endif # define free(p) delete[] (char*)(p) -# define default_free free # endif /** @@ -140,29 +161,29 @@ extern const char* new_progname; // default to NULL; should be * * The idea comes from <a href="http://groups.google.com/group/comp.lang.c++.moderated/browse_thread/thread/7089382e3bc1c489/85f9107a1dc79ee9?#85f9107a1dc79ee9">Greg Herlihy's post</a> in comp.lang.c++.moderated. */ -class __debug_new_recorder +class debug_new_recorder { - const char* _M_file; - const int _M_line; - void _M_process(void* pointer); - public: - /** - * Constructor to remember the call context. The information will - * be used in __debug_new_recorder::operator->*. - */ - __debug_new_recorder(const char* file, int line) - : _M_file(file), _M_line(line) {} - /** - * Operator to write the context information to memory. - * <code>operator->*</code> is chosen because it has the right - * precedence, it is rarely used, and it looks good: so people can - * tell the special usage more quickly. - */ - template <class _Tp> _Tp* operator->*(_Tp* pointer) - { _M_process(pointer); return pointer; } - private: - __debug_new_recorder(const __debug_new_recorder&); - __debug_new_recorder& operator=(const __debug_new_recorder&); + const char* _M_file; + const int _M_line; + void _M_process(void* ptr); +public: + /** + * Constructor to remember the call context. The information will + * be used in debug_new_recorder::operator->*. + */ + debug_new_recorder(const char* file, int line) + : _M_file(file), _M_line(line) {} + /** + * Operator to write the context information to memory. + * <code>operator->*</code> is chosen because it has the right + * precedence, it is rarely used, and it looks good: so people can + * tell the special usage more quickly. + */ + template <class _Tp> _Tp* operator->*(_Tp* ptr) + { _M_process(ptr); return ptr; } +private: + debug_new_recorder(const debug_new_recorder&); + debug_new_recorder& operator=(const debug_new_recorder&); }; /** @@ -171,14 +192,16 @@ class __debug_new_recorder * This technique is learnt from <em>The C++ Programming Language</em> by * Bjarne Stroustup. */ -class __debug_new_counter +class debug_new_counter { - static int _S_count; - public: - __debug_new_counter(); - ~__debug_new_counter(); + static int _S_count; +public: + debug_new_counter(); + ~debug_new_counter(); }; /** Counting object for each file including debug_new.h. */ -static __debug_new_counter __debug_new_count; +static debug_new_counter __debug_new_count; + +NVWA_NAMESPACE_END -#endif // M_DEBUG_NEW_H +#endif // NVWA_DEBUG_NEW_H |