diff --git a/dtool/Config.pp b/dtool/Config.pp index 3cd9caaf78..c80403beeb 100644 --- a/dtool/Config.pp +++ b/dtool/Config.pp @@ -327,6 +327,11 @@ // available, even if it is unused. #defer DO_MEMORY_USAGE $[<= $[OPTIMIZE], 3] +// Should we attempt to override the global new and delete operators? +// It turns out this is usually a bad idea, but may be useful for +// development. +#define REDEFINE_GLOBAL_OPERATOR_NEW + // This option compiles in support for simulating network delay via // the min-lag and max-lag prc variables. It adds a tiny bit of // overhead even when it is not activated, so it is typically enabled diff --git a/dtool/LocalSetup.pp b/dtool/LocalSetup.pp index 9dca3ffbfe..9e3ee79509 100644 --- a/dtool/LocalSetup.pp +++ b/dtool/LocalSetup.pp @@ -275,6 +275,7 @@ $[cdefine TRACK_IN_INTERPRETER] /* Define if we want to enable track-memory-usage. */ $[cdefine DO_MEMORY_USAGE] +$[cdefine REDEFINE_GLOBAL_OPERATOR_NEW] /* Define if we want to enable min-lag and max-lag. */ $[cdefine SIMULATE_NETWORK_DELAY] diff --git a/dtool/src/cppparser/cppPreprocessor.cxx b/dtool/src/cppparser/cppPreprocessor.cxx index 96573446c4..2184a96ac8 100644 --- a/dtool/src/cppparser/cppPreprocessor.cxx +++ b/dtool/src/cppparser/cppPreprocessor.cxx @@ -106,7 +106,7 @@ CPPPreprocessor::InputFile:: // the stream pointer does not call the appropriate global delete // function; instead apparently calling the system delete // function. So we call the delete function by hand instead. -#ifndef USE_MEMORY_NOWRAPPERS +#if !defined(USE_MEMORY_NOWRAPPERS) && defined(REDEFINE_GLOBAL_OPERATOR_NEW) _in->~istream(); (*global_operator_delete)(_in); #else diff --git a/dtool/src/dtoolbase/Sources.pp b/dtool/src/dtoolbase/Sources.pp index dc757d97af..0f83cbcd51 100644 --- a/dtool/src/dtoolbase/Sources.pp +++ b/dtool/src/dtoolbase/Sources.pp @@ -19,6 +19,7 @@ dtoolbase.h dtoolbase_cc.h dtoolsymbols.h \ fakestringstream.h \ indent.I indent.h indent.cxx \ + memoryBase.h \ mutexImpl.h \ mutexDummyImpl.h mutexDummyImpl.I \ mutexNsprImpl.h mutexNsprImpl.I \ @@ -62,6 +63,7 @@ deletedChain.h deletedChain.T \ dtoolbase.h dtoolbase_cc.h dtoolsymbols.h fakestringstream.h \ indent.I indent.h \ + memoryBase.h \ mutexImpl.h \ mutexDummyImpl.h mutexDummyImpl.I \ mutexNsprImpl.h mutexNsprImpl.I \ diff --git a/dtool/src/dtoolbase/dtoolbase_cc.h b/dtool/src/dtoolbase/dtoolbase_cc.h index 205776ccd4..b6792ddda4 100644 --- a/dtool/src/dtoolbase/dtoolbase_cc.h +++ b/dtool/src/dtoolbase/dtoolbase_cc.h @@ -147,6 +147,7 @@ EXPCL_DTOOL void default_operator_delete(void *ptr); extern EXPCL_DTOOL void *(*global_operator_new)(size_t size); extern EXPCL_DTOOL void (*global_operator_delete)(void *ptr); +#ifdef REDEFINE_GLOBAL_OPERATOR_NEW #ifdef GLOBAL_OPERATOR_NEW_EXCEPTIONS // Redefinitions of operator new/delete, for O1 - O3 builds (!NDEBUG) @@ -184,6 +185,7 @@ INLINE void operator delete[](void *ptr) { } #endif // GLOBAL_OPERATOR_NEW_EXCEPTIONS +#endif // REDEFINE_GLOBAL_OPERATOR_NEW #endif // USE_MEMORY_NOWRAPPERS #if defined(USE_TAU) && defined(WIN32) diff --git a/dtool/src/dtoolbase/memoryBase.h b/dtool/src/dtoolbase/memoryBase.h new file mode 100644 index 0000000000..3e8846aa4c --- /dev/null +++ b/dtool/src/dtoolbase/memoryBase.h @@ -0,0 +1,83 @@ +// Filename: memoryBase.h +// Created by: drose (16Nov06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef MEMORYBASE_H +#define MEMORYBASE_H + +#include "dtoolbase.h" + +// Place this macro within a class definition to define appropriate +// operator new and delete methods that hook into the MemoryInfo class +// to provide memory tracking. Of course, it is better simply to +// inherit from MemoryBase; this macro is provided to resolve problems +// with multiple inheritance or some such. + +#ifndef USE_MEMORY_NOWRAPPERS + +#define ALLOC_MEMORY_BASE \ + inline void *operator new(size_t size) { \ + return (*global_operator_new)(size); \ + } \ + inline void *operator new(size_t size, void *) { \ + return (*global_operator_new)(size); \ + } \ + inline void operator delete(void *ptr) { \ + (*global_operator_delete)(ptr); \ + } \ + inline void operator delete(void *ptr, void *) { \ + (*global_operator_delete)(ptr); \ + } \ + inline void *operator new[](size_t size) { \ + return (*global_operator_new)(size); \ + } \ + inline void *operator new[](size_t size, void *) { \ + return (*global_operator_new)(size); \ + } \ + inline void operator delete[](void *ptr) { \ + (*global_operator_delete)(ptr); \ + } \ + inline void operator delete[](void *ptr, void *) { \ + (*global_operator_delete)(ptr); \ + } + +#else // USE_MEMORY_NOWRAPPERS + +#define ALLOC_MEMORY_BASE + +#endif // USE_MEMORY_NOWRAPPERS + +//////////////////////////////////////////////////////////////////// +// Class : MemoryBase +// Description : This class is intended to be the base class of all +// objects in Panda that might be allocated and deleted +// via the new and delete operators. It redefines these +// operators to provide some memory tracking support. +// +// We used to try to override the global operator new +// and delete methods, but that seems to cause problems +// when including header files for C++-based system +// libraries (such as are found on OSX). +//////////////////////////////////////////////////////////////////// +class EXPCL_DTOOL MemoryBase { +public: + ALLOC_MEMORY_BASE; +}; + +#endif + + diff --git a/dtool/src/interrogatedb/typeRegistry.h b/dtool/src/interrogatedb/typeRegistry.h index 091106d0a7..1b9dec2dc3 100644 --- a/dtool/src/interrogatedb/typeRegistry.h +++ b/dtool/src/interrogatedb/typeRegistry.h @@ -24,6 +24,7 @@ #include "pnotify.h" #include "pvector.h" #include "pmap.h" +#include "memoryBase.h" #include @@ -40,7 +41,7 @@ class TypedObject; // initially, and it should be migrated to shared memory // as soon as shared memory becomes available. //////////////////////////////////////////////////////////////////// -class EXPCL_DTOOLCONFIG TypeRegistry { +class EXPCL_DTOOLCONFIG TypeRegistry : public MemoryBase { public: // User code shouldn't generally need to call // TypeRegistry::register_type() or record_derivation() directly; diff --git a/dtool/src/interrogatedb/typedObject.h b/dtool/src/interrogatedb/typedObject.h index ee53b285ab..3f138f1faa 100644 --- a/dtool/src/interrogatedb/typedObject.h +++ b/dtool/src/interrogatedb/typedObject.h @@ -23,6 +23,7 @@ #include "typeHandle.h" #include "register_type.h" +#include "memoryBase.h" #include @@ -104,7 +105,7 @@ // } // //////////////////////////////////////////////////////////////////// -class EXPCL_DTOOLCONFIG TypedObject { +class EXPCL_DTOOLCONFIG TypedObject : public MemoryBase { public: INLINE TypedObject(); INLINE TypedObject(const TypedObject ©); diff --git a/panda/src/downloader/httpChannel.cxx b/panda/src/downloader/httpChannel.cxx index 3c74e1d08f..4037a1e2c4 100644 --- a/panda/src/downloader/httpChannel.cxx +++ b/panda/src/downloader/httpChannel.cxx @@ -190,7 +190,7 @@ close_read_file(istream *stream) const { // the stream pointer does not call the appropriate global delete // function; instead apparently calling the system delete // function. So we call the delete function by hand instead. -#ifndef USE_MEMORY_NOWRAPPERS +#if !defined(USE_MEMORY_NOWRAPPERS) && defined(REDEFINE_GLOBAL_OPERATOR_NEW) stream->~istream(); (*global_operator_delete)(stream); #else diff --git a/panda/src/express/memoryUsage.cxx b/panda/src/express/memoryUsage.cxx index 3d9cccb90b..43a054b1ba 100644 --- a/panda/src/express/memoryUsage.cxx +++ b/panda/src/express/memoryUsage.cxx @@ -603,6 +603,7 @@ ns_record_void_pointer(void *ptr, size_t size) { if ((info._flags & MemoryInfo::F_got_void) != 0) { express_cat.error() << "Void pointer " << (void *)ptr << " recorded twice!\n"; + nassertv(false); } if (info._freeze_index == _freeze_index) { diff --git a/panda/src/express/referenceCount.h b/panda/src/express/referenceCount.h index d563525e46..96235d4f50 100644 --- a/panda/src/express/referenceCount.h +++ b/panda/src/express/referenceCount.h @@ -23,6 +23,7 @@ #include "weakReferenceList.h" #include "typedObject.h" #include "memoryUsage.h" +#include "memoryBase.h" #include "config_express.h" #include "atomicAdjust.h" #include "numeric_types.h" @@ -42,7 +43,7 @@ // conjunction with PointerTo to automatically delete // objects when the last pointer to them goes away. //////////////////////////////////////////////////////////////////// -class EXPCL_PANDAEXPRESS ReferenceCount { +class EXPCL_PANDAEXPRESS ReferenceCount : public MemoryBase { protected: INLINE ReferenceCount(); INLINE ReferenceCount(const ReferenceCount &); diff --git a/panda/src/express/virtualFile.cxx b/panda/src/express/virtualFile.cxx index 65b38de911..10c8e22870 100644 --- a/panda/src/express/virtualFile.cxx +++ b/panda/src/express/virtualFile.cxx @@ -223,7 +223,7 @@ close_read_file(istream *stream) const { // the stream pointer does not call the appropriate global delete // function; instead apparently calling the system delete // function. So we call the delete function by hand instead. -#ifndef USE_MEMORY_NOWRAPPERS +#if !defined(USE_MEMORY_NOWRAPPERS) && defined(REDEFINE_GLOBAL_OPERATOR_NEW) stream->~istream(); (*global_operator_delete)(stream); #else diff --git a/panda/src/express/virtualFileMount.cxx b/panda/src/express/virtualFileMount.cxx index 768efa2a25..b18b4f390c 100644 --- a/panda/src/express/virtualFileMount.cxx +++ b/panda/src/express/virtualFileMount.cxx @@ -46,7 +46,7 @@ close_read_file(istream *stream) const { // the stream pointer does not call the appropriate global delete // function; instead apparently calling the system delete // function. So we call the delete function by hand instead. -#ifndef USE_MEMORY_NOWRAPPERS +#if !defined(USE_MEMORY_NOWRAPPERS) && defined(REDEFINE_GLOBAL_OPERATOR_NEW) stream->~istream(); (*global_operator_delete)(stream); #else diff --git a/panda/src/express/virtualFileSystem.cxx b/panda/src/express/virtualFileSystem.cxx index 74f14b65a8..61e31df87b 100644 --- a/panda/src/express/virtualFileSystem.cxx +++ b/panda/src/express/virtualFileSystem.cxx @@ -607,7 +607,7 @@ close_read_file(istream *stream) const { // the stream pointer does not call the appropriate global delete // function; instead apparently calling the system delete // function. So we call the delete function by hand instead. -#ifndef USE_MEMORY_NOWRAPPERS +#if !defined(USE_MEMORY_NOWRAPPERS) && defined(REDEFINE_GLOBAL_OPERATOR_NEW) stream->~istream(); (*global_operator_delete)(stream); #else