]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
MemPool the debug output stream buffers
authorAmos Jeffries <squid3@treenet.co.nz>
Fri, 19 Dec 2014 16:26:44 +0000 (08:26 -0800)
committerAmos Jeffries <squid3@treenet.co.nz>
Fri, 19 Dec 2014 16:26:44 +0000 (08:26 -0800)
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<char> 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

src/Debug.h
src/debug.cc
src/tests/stub_debug.cc

index 7d0509a42a636c01184f9eeeb6618a67a8e83d8d..41ea2fe61058075e3c16f9d426a4bb0bf8520594 100644 (file)
@@ -67,7 +67,19 @@ private:
     // 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
 };
 
index 869dd37657bab68d6a23260eca455079f54d26e6..1d6335196f8d9e828c7bbeb66df4a83a4b7529e8 100644 (file)
@@ -709,6 +709,8 @@ ctx_get_descr(Ctx ctx)
 
 int Debug::TheDepth = 0;
 
+Debug::OutStream *Debug::CurrentDebug(NULL);
+
 std::ostream &
 Debug::getDebugOut()
 {
@@ -719,7 +721,7 @@ Debug::getDebugOut()
         *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 @@ Debug::xassert(const char *msg, const char *file, int line)
     abort();
 }
 
-std::ostringstream (*Debug::CurrentDebug)(NULL);
-
 size_t
 BuildPrefixInit()
 {
index 7412640120c356b8a6f424730359de5303da711b..dea7c3c76e82ab9fe263b49cdfe1d694ce6c9cf1 100644 (file)
@@ -87,6 +87,8 @@ _db_print_stderr(const char *format, va_list args)
     vfprintf(stderr, format, args);
 }
 
+Debug::OutStream *Debug::CurrentDebug(NULL);
+
 std::ostream &
 Debug::getDebugOut()
 {
@@ -97,7 +99,7 @@ Debug::getDebugOut()
         *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 @@ Debug::xassert(const char *msg, const char *file, int line)
     abort();
 }
 
-std::ostringstream *Debug::CurrentDebug (NULL);
-
 const char*
 SkipBuildPrefix(const char* path)
 {