libcwd: The C++ Debugging Support Library - Reference Manual
Author: Carlo Wood
Description: C++ debugging support library with ostream debug output
Keywords: libcwd, debug output, debug facility, debug channel, object orientation, OO, C++, nested debug output, ostream, memory allocation, debugging, source file and line number

Main Page Reference Manual Namespace List Compound List Namespace Members Compound Members File Members

# libcwd/macro_AllocTag.h

Go to the documentation of this file.

    00001 // $Header$
    00002 //
    00003 // Copyright (C) 2000 - 2004, by
    00004 //
    00005 // Carlo Wood, Run on IRC <carlo@alinoe.com>
    00006 // RSA-1024 0x624ACAD5 1997-01-26                    Sign & Encrypt
    00007 // Fingerprint16 = 32 EC A7 B6 AC DB 65 A6  F6 F6 55 DD 1C DC FF 61
    00008 //
    00009 // This file may be distributed under the terms of the Q Public License
    00010 // version 1.0 as appearing in the file LICENSE.QPL included in the
    00011 // packaging of this file.
    00012 //
    00013
    00018 #ifndef LIBCWD_MACRO_ALLOCTAG_H
    00019 #define LIBCWD_MACRO_ALLOCTAG_H
    00020
    00021 #ifndef LIBCWD_LIBRARIES_DEBUG_H
    00022 #error "Don't include <libcwd/macro_AllocTag.h> directly, include the appropriate \"debug.h\" instead."
    00023 #endif
    00024
    00025 #ifndef LIBCWD_CONFIG_H
    00026 #include <libcwd/config.h>
    00027 #endif
    00028
    00029 #if CWDEBUG_ALLOC
    00030
    00031 #ifndef LIBCW_CSTDDEF
    00032 #define LIBCW_CSTDDEF
    00033 #include <cstddef>              // Needed for size_t.
    00034 #endif
    00035 #ifndef LIBCWD_SMART_PTR_H
    00036 #include <libcwd/smart_ptr.h>
    00037 #endif
    00038 #ifndef LIBCWD_PRIVATE_SET_ALLOC_CHECKING_H
    00039 #include <libcwd/private_set_alloc_checking.h>
    00040 #endif
    00041 #ifndef LIBCWD_TYPE_INFO_H
    00042 #include <libcwd/type_info.h>
    00043 #endif
    00044 #ifndef LIBCWD_PRIVATE_INTERNAL_STRINGSTREAM_H
    00045 #include <libcwd/private_internal_stringstream.h>
    00046 #endif
    00047
    00048 namespace libcwd {
    00049
    00053 // Undocumented (used inside AllocTag, AllocTag_dynamic_description, AllocTag1 and AllocTag2):
    00054 extern void set_alloc_label(void const* ptr, type_info_ct const& ti, char const* description LIBCWD_COMMA_TSD_PARAM);
    00055     // For static descriptions
    00056 extern void set_alloc_label(void const* ptr, type_info_ct const& ti, _private_::smart_ptr description LIBCWD_COMMA_TSD_PARAM);
    00057     // For dynamic descriptions
    00058     // allocated with new[]
    00059 extern char* allocate_AllocTag_WS_desc(size_t size);
    00060 #ifndef LIBCWD_USE_EXTERNAL_C_LINKAGE_FOR_MALLOC
    00061 extern void register_external_allocation(void const* ptr, size_t size);
    00062 #endif
    00063  // End of group 'group_annotation'.
    00065
    00066 } // namespace libcwd
    00067
    00068 //===================================================================================================
    00069 // Macro AllocTag
    00070 //
    00071
    00135 #define AllocTag1(p) \
    00136     do { \
    00137       LIBCWD_TSD_DECLARATION; \
    00138       ::libcwd::set_alloc_label(p, ::libcwd::type_info_of(p), (char const*)NULL LIBCWD_COMMA_TSD); \
    00139     } while(0)
    00140
    00143 #define AllocTag2(p, desc) \
    00144     do { \
    00145       LIBCWD_TSD_DECLARATION; \
    00146       ::libcwd::set_alloc_label(p, ::libcwd::type_info_of(p), const_cast<char const*>(desc) LIBCWD_COMMA_TSD); \
    00147     } while(0)
    00148
    00149 #if LIBCWD_THREAD_SAFE
    00150 #define LIBCWD_ALLOCTAG_LOCK \
    00151     if (!WS_desc) \
    00152     { \
    00153       static pthread_mutex_t WS_desc_mutex = PTHREAD_MUTEX_INITIALIZER; \
    00154       pthread_mutex_lock(&WS_desc_mutex);
    00155 #define LIBCWD_ALLOCTAG_UNLOCK \
    00156       pthread_mutex_unlock(&WS_desc_mutex); \
    00157     }
    00158 #else
    00159 #define LIBCWD_ALLOCTAG_LOCK
    00160 #define LIBCWD_ALLOCTAG_UNLOCK
    00161 #endif
    00162
    00166 #define AllocTag(p, x) \
    00167     do { \
    00168       LIBCWD_TSD_DECLARATION; \
    00169       static char* WS_desc; \
    00170       LIBCWD_ALLOCTAG_LOCK; \
    00171       if (!WS_desc) { \
    00172         ++LIBCWD_DO_TSD_MEMBER_OFF(::libcwd::libcw_do); \
    00173         if (1) \
    00174         { \
    00175           ::libcwd::_private_::auto_internal_stringstream buf; \
    00176           buf << x << ::std::ends; \
    00177           ::std::streampos pos = buf.rdbuf()->pubseekoff(0, ::std::ios_base::cur, ::std::ios_base::out); \
    00178           size_t size = pos - ::std::streampos(0); \
    00179           ::libcwd::_private_::set_alloc_checking_off(LIBCWD_TSD); \
    00180           WS_desc = ::libcwd::allocate_AllocTag_WS_desc(size); /* This is never deleted anymore */ \
    00181           ::libcwd::_private_::set_alloc_checking_on(LIBCWD_TSD); \
    00182           buf.rdbuf()->sgetn(WS_desc, size); \
    00183         } \
    00184         --LIBCWD_DO_TSD_MEMBER_OFF(::libcwd::libcw_do); \
    00185       } \
    00186       LIBCWD_ALLOCTAG_UNLOCK; \
    00187       ::libcwd::set_alloc_label(p, ::libcwd::type_info_of(p), WS_desc LIBCWD_COMMA_TSD); \
    00188     } while(0)
    00189
    00193 #define AllocTag_dynamic_description(p, x) \
    00194     do { \
    00195       char* desc; \
    00196       LIBCWD_TSD_DECLARATION; \
    00197       ++LIBCWD_DO_TSD_MEMBER_OFF(::libcwd::libcw_do); \
    00198       if (1) \
    00199       { \
    00200         ::libcwd::_private_::auto_internal_stringstream buf; \
    00201         buf << x << ::std::ends; \
    00202         ::std::streampos pos = buf.rdbuf()->pubseekoff(0, ::std::ios_base::cur, ::std::ios_base::out); \
    00203         size_t size = pos - ::std::streampos(0); \
    00204         ::libcwd::_private_::set_alloc_checking_off(LIBCWD_TSD); \
    00205         desc = new char [size]; \
    00206         ::libcwd::_private_::set_alloc_checking_on(LIBCWD_TSD); \
    00207         buf.rdbuf()->sgetn(desc, size); \
    00208       } \
    00209       --LIBCWD_DO_TSD_MEMBER_OFF(::libcwd::libcw_do); \
    00210       ::libcwd::set_alloc_label(p, ::libcwd::type_info_of(p), \
    00211                                       ::libcwd::_private_::smart_ptr(desc) LIBCWD_COMMA_TSD); \
    00212     } while(0)
    00213
    00214 template<typename TYPE>
    00215 #ifndef __FreeBSD__
    00216   // There is a bug in g++ that causes the wrong line number information to be generated
    00217   // when this function is inline.  I was able to use heuristics to work around that for
    00218   // STABS, but not for DWARF-2 (the default of FreeBSD).
    00219   // See http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=5271
    00220   inline
    00221 #endif
    00222   TYPE*
    00223   __libcwd_allocCatcher(TYPE* new_ptr)
    00224   {
    00225     AllocTag1(new_ptr);
    00226     return new_ptr;
    00227   }
    00228
    00232 #define NEW(x) __libcwd_allocCatcher(new x)
    00233
    00234 #ifndef LIBCWD_USE_EXTERNAL_C_LINKAGE_FOR_MALLOC
    00235
    00238 #define RegisterExternalAlloc(p, s) ::libcwd::register_external_allocation(p, s)
    00239 #endif
    00240  // End of group 'group_annotation'.
    00242
    00243 #else // !CWDEBUG_ALLOC
    00244
    00248 #define AllocTag(p, x)
    00249 #define AllocTag_dynamic_description(p, x)
    00250 #define AllocTag1(p)
    00251 #define AllocTag2(p, desc)
    00252 #define NEW(x) new x
    00253 #ifndef LIBCWD_USE_EXTERNAL_C_LINKAGE_FOR_MALLOC
    00254 #define RegisterExternalAlloc(p, s)
    00255 #endif
    00256  // End of group 'group_annotation'.
    00258
    00259 #endif // !CWDEBUG_ALLOC
    00260
    00261 #endif // LIBCWD_MACRO_ALLOCTAG_H
    00262