------------------------------------------------------------ revno: 13698 revision-id: squid3@treenet.co.nz-20141220160028-0fmjbyorgqqojpyh parent: squid3@treenet.co.nz-20141220154801-9d5glea7sjcn394q committer: Amos Jeffries branch nick: 3.5 timestamp: Sat 2014-12-20 08:00:28 -0800 message: MemPool the debug output stream buffers The CurrentDebug output stream controller for cache.log was defined as a std::ostringstream object and allocated with new/delete on each call to debugs(). The std::ostringstream is defined as a templates output stream which uses the std::allocator built into libc when its new()'d. Since this is all internal to the STL library definitions it links against the libc global-scope allocator. However, there is no matching deallocator definition and when the object is delete()'d the standard C++ operator overloading rules make the global-scope SquidNew.h definition of ::operator delete() be the method of deallocation. That uses free() internally. To resolve the mismatch of new()/free() we must define a wrapper class with explicit class-scope new/delete operators instead of relying on weak linkages to overloaded global scope operators. As a result the memory is new()'d and free()'d. As detected by Valgrind ------------------------------------------------------------ # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: squid3@treenet.co.nz-20141220160028-0fmjbyorgqqojpyh # target_branch: http://bzr.squid-cache.org/bzr/squid3/3.5 # testament_sha1: db29878326f09d4e5dc3995342bde8a0748cbdbd # timestamp: 2014-12-20 16:38:46 +0000 # source_branch: http://bzr.squid-cache.org/bzr/squid3/3.5 # base_revision_id: squid3@treenet.co.nz-20141220154801-\ # 9d5glea7sjcn394q # # Begin patch === modified file 'src/Debug.h' --- src/Debug.h 2014-09-13 13:59:43 +0000 +++ src/Debug.h 2014-12-20 16:00:28 +0000 @@ -67,7 +67,19 @@ // Hack: replaces global ::xassert() to debug debugging assertions static void xassert(const char *msg, const char *file, int line); - static std::ostringstream *CurrentDebug; + /// Wrapper class to prevent SquidNew.h overrides getting confused + /// with the libc++6 std::ostringstream definitions + class OutStream : public std::ostringstream + { + // XXX: use MEMPROXY_CLASS() once that no longer pulls in typedefs.h and enums.h and globals.h + public: + void *operator new(size_t size) throw(std::bad_alloc) {return xmalloc(size);} + void operator delete(void *address) throw() {xfree(address);} + void *operator new[] (size_t size) throw(std::bad_alloc) ; //{return xmalloc(size);} + void operator delete[] (void *address) throw() ; // {xfree(address);} + }; + + static OutStream *CurrentDebug; static int TheDepth; // level of nested debugging calls }; === modified file 'src/debug.cc' --- src/debug.cc 2014-09-13 13:59:43 +0000 +++ src/debug.cc 2014-12-20 16:00:28 +0000 @@ -709,6 +709,8 @@ int Debug::TheDepth = 0; +Debug::OutStream *Debug::CurrentDebug(NULL); + std::ostream & Debug::getDebugOut() { @@ -719,7 +721,7 @@ *CurrentDebug << std::endl << "reentrant debuging " << TheDepth << "-{"; } else { assert(!CurrentDebug); - CurrentDebug = new std::ostringstream(); + CurrentDebug = new Debug::OutStream; // set default formatting flags CurrentDebug->setf(std::ios::fixed); CurrentDebug->precision(2); @@ -756,8 +758,6 @@ abort(); } -std::ostringstream (*Debug::CurrentDebug)(NULL); - size_t BuildPrefixInit() { === modified file 'src/tests/stub_debug.cc' --- src/tests/stub_debug.cc 2014-09-12 23:00:48 +0000 +++ src/tests/stub_debug.cc 2014-12-20 16:00:28 +0000 @@ -87,6 +87,8 @@ vfprintf(stderr, format, args); } +Debug::OutStream *Debug::CurrentDebug(NULL); + std::ostream & Debug::getDebugOut() { @@ -97,7 +99,7 @@ *CurrentDebug << std::endl << "reentrant debuging " << TheDepth << "-{"; } else { assert(!CurrentDebug); - CurrentDebug = new std::ostringstream(); + CurrentDebug = new Debug::OutStream; // set default formatting flags CurrentDebug->setf(std::ios::fixed); CurrentDebug->precision(2); @@ -138,8 +140,6 @@ abort(); } -std::ostringstream *Debug::CurrentDebug (NULL); - const char* SkipBuildPrefix(const char* path) {