Mailing-List: contact cygwin-help AT sourceware DOT cygnus DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT sources DOT redhat DOT com Delivered-To: mailing list cygwin AT sources DOT redhat DOT com Message-ID: <9BBB0C9AF506D311A68E00902745A53703CC798D@fsxqpz04.usafa.af.mil> From: Andrews Harold G Maj USAFA/DFCS To: "'David Acton'" Cc: "'cygwin AT cygwin DOT com'" Subject: RE: gcc bug - temporary objects not destroyed properly Date: Tue, 9 Oct 2001 11:55:25 -0600 MIME-Version: 1.0 X-Mailer: Internet Mail Service (5.5.2653.19) Content-Type: text/plain Mr. Acton, I've seen something similar with gcc 2.95 under Cygwin. The main difference was that I had at least one virtual method in my class. The compiler (using the -Wall option) mentioned that I should declare a *virtual* destructor. The one I created was was essentially empty, and seemed to fix the problem (though I'm not completely certain why that was). This might be something that could fix your problem if you want to continue using GCC 2.95.x BTW, I was not able to repeat the error using GCC 3.0.1 (though there were some simple-to-fix compiler errors). You might want to consider upgrading. -Andy ================================================================ Harold G. "Andy" Andrews II, Ph.D., Major, USAF Assistant Professor, Department of Computer Science United States Air Force Academy Room 1J-148 Fairchild Hall DSN: 333-7553 Comm: (719) 333-7553 ================================================================ -----Original Message----- From: David Acton [mailto:da AT alphawave DOT net] Sent: Tuesday, October 09, 2001 9:37 AM To: cygwin AT cygwin DOT com Subject: gcc bug - temporary objects not destroyed properly Hi, 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); // ^^^^^^^^^^ this is the object that doesn't get destroyed! 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 #include class Example; static list 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::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 the Stroustrup way... 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); // ^^^^^^^^^^ this 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::const_iterator i = track.begin(); i != track.end(); ++i) { printf(" object at %p\n", (void *)*i); } } } //-------------------------------------------------------------------------- ------ My colleague Nick Craig-Wood was kind enough to try out the above with the different compilers described and thus confirm the bug. Hope this is of some help to you! Cheers -- David Acton Alphawave Ltd -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Bug reporting: http://cygwin.com/bugs.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/ -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Bug reporting: http://cygwin.com/bugs.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/