From: <no...@so...> - 2001-10-09 15:23:32
|
Bugs item #469566, was opened at 2001-10-09 08:23 You can respond by visiting: http://sourceforge.net/tracker/?func=detail&atid=102435&aid=469566&group_id=2435 Category: gcc Group: None Status: Open Resolution: None Priority: 5 Submitted By: Nobody/Anonymous (nobody) Assigned to: Nobody/Anonymous (nobody) Summary: temporary objects not destroyed Initial Comment: Here is a short test program to reproduce a bug we've discovered with gcc 2.95.3 targeted at Win32 (either cygwin or mingw). The bug manifests itself as temporary objects which aren't destroyed. This caused a large memory leak in our program. We narrowed it down to a single form of statement: return _condition ? Example(2) + Example(3) : Example(4); It seems to need the return, the ? : and the creation of a temporary object to trigger the bug. Unfortunately our code had rather a lot of these statements in! Compile the test program with: gcc -Wall -pedantic cpp_bug.cc -o cpp_bug -lstdc++ It produces this when compiled native under linux Reading specs from /usr/local/lib/gcc-lib/i686-pc-linux-gnu/2.95.3/specs gcc version 2.95.3 20010315 (release) Testing... Creating object with value 42 at 0xbffffa10 Creating object with value 3 at 0xbffff9b0 Creating object with value 2 at 0xbffff9a0 Creating object with value 2 at 0xbffff960 from another Creating object with value 5 at 0xbffffa00 from another result = 5 However when compiled under native Windows cygwin it produces Reading specs from /usr/lib/gcc-lib/i686-pc-cygwin/2.95.3-5/specs gcc version 2.95.3-5 (cygwin special) Testing... Creating object with value 42 at 0x7afd1c Creating object with value 3 at 0x7afc94 Creating object with value 2 at 0x7afc64 Creating object with value 2 at 0x7afbb4 from another Creating object with value 5 at 0x7afcfc from another result = 5 Oh no - 1 temporary object(s) did not have their destructors called! object at 0x7afc64 Likewise when compiled under a cross compiled mingw Reading specs from /usr/local/cross/mingw/lib/gcc-lib/i386-mingw32msvc/2.95.2/specs gcc version 2.95.2 19991024 (release) Testing... Creating object with value 42 at 0259FDC8 Creating object with value 3 at 0259FD40 Creating object with value 2 at 0259FD10 Creating object with value 2 at 0259FC60 from another Creating object with value 5 at 0259FDA8 from another result = 5 Oh no - 1 temporary object(s) did not have their destructors called! object at 0259FD10 Likewise or under a newer mingw Reading specs from /usr/local/cross-tools/lib/gcc-lib/mingw32/2.95.3/specs gcc version 2.95.3 20010315 (release) Testing... Creating object with value 42 at 0081FDC8 Creating object with value 3 at 0081FD40 Creating object with value 2 at 0081FD10 Creating object with value 2 at 0081FC60 from another Creating object with value 5 at 0081FDA8 from another result = 5 Oh no - 1 temporary object(s) did not have their destructors called! object at 0081FD10 */ //-------------------------------------------------------------------------------- /* test compiler for obscure C++ memory leak! */ #include <stdio.h> #include <list> class Example; static list<Example *> track; // we keep track of all objects created and destroyed using this list class Example { public: Example(const int _value); Example(const Example & _a); ~Example(); Example & operator+=(const Example & _a); const int get_value() const { return value; } Example test(const bool _condition); private: int value; }; Example::Example(const int _value) { printf("Creating object with value %d at %p\n", _value, (void *)this); value = _value; track.push_back(this); } Example::Example(const Example & _a) { printf("Creating object with value %d at %p from another\n", _a.get_value(), (void *)this); value = _a.get_value(); track.push_back(this); } Example::~Example() { for (list<Example *>::iterator i = track.begin(); i != track.end(); ++i) { if ((*i) == this) { track.erase(i); return; } } printf("Oops! Cannot find object of value %d at %p in list\n", value, (void *)this); } // We define + and += operators for our object in the manner recommended by Stroustrup... Example & Example::operator+=(const Example & _a) { value += _a.get_value(); return *this; } Example operator+(const Example & _a, const Example & _b) { Example c(_a); c += _b; return c; } Example Example::test(const bool _condition) { return _condition ? Example(2) + Example(3) : Example(4); // Example(2) is the object that doesn't get destroyed! } int main (int argc, char *argv[]) { printf("Testing...\n"); // Do our little test - put in a scope of its own so all the temporary objects *should* get destroyed... { Example eg(42); printf("result = %d\n", eg.test(true).get_value()); } if (!track.empty()) { printf("Oh no - %d temporary object(s) did not have their destructors called!\n", track.size()); for (list<Example *>::const_iterator i = track.begin(); i != track.end(); ++i) { printf(" object at %p\n", (void *)*i); } } } ---------------------------------------------------------------------- You can respond by visiting: http://sourceforge.net/tracker/?func=detail&atid=102435&aid=469566&group_id=2435 |