By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,407 Members | 1,074 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,407 IT Pros & Developers. It's quick & easy.

Possible memory leak?

P: n/a
Pep
I have recently eradicated a lot of memory leaks in a very old C++
source set. However, whilst they were all fairly easy to resolve, I am
confused by the last one. This seems to be related to throwing a
std::exception with a string object.

This is the test program

================================================== ===========================
#include <sstream>
#include <iostream>
#include <stdlib.h>
#include <stdexcept>

int main(int argc, char** argv)
{
std::ostringstream os;
os << "Test string";
throw std::out_of_range(os.str());

return(0);
}
================================================== ===========================

and this is the output from valgrind when I run it

================================================== ===========================
[pw*****@mgr1.tweb.eudev1 trunk]$ g++ -o test-ostringstream test-
ostringstream.cc
[pw*****@mgr1.tweb.eudev1 trunk]$ valgrind --leak-check=yes ./test-
ostringstream
==23358== Memcheck, a memory error detector.
==23358== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et
al.
==23358== Using LibVEX rev 1854, a library for dynamic binary
translation.
==23358== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP.
==23358== Using valgrind-3.3.1, a dynamic binary instrumentation
framework.
==23358== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et
al.
==23358== For more details, rerun with: -v
==23358==
==23358==
==23358== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 19 from
1)
==23358== malloc/free: in use at exit: 2,184 bytes in 3 blocks.
==23358== malloc/free: 3 allocs, 0 frees, 2,184 bytes allocated.
==23358== For counts of detected errors, rerun with: -v
==23358== searching for pointers to 3 not-freed blocks.
==23358== checked 104,152 bytes.
==23358==
==23358== 960 bytes in 1 blocks are possibly lost in loss record 2 of
3
==23358== at 0x401AD81: operator new(unsigned) (vg_replace_malloc.c:
224)
==23358== by 0x409D0F0: std::__default_alloc_template<true,
0>::_S_chunk_alloc(unsigned, int&) (stl_alloc.h:109)
==23358== by 0x409CFFC: std::__default_alloc_template<true,
0>::_S_refill(unsigned) (stl_alloc.h:561)
==23358== by 0x409CB6B: std::__default_alloc_template<true,
0>::allocate(unsigned) (stl_alloc.h:365)
==23358== by 0x40A2B67: std::string::_Rep::_S_create(unsigned,
std::allocator<charconst&) (stl_alloc.h:685)
==23358== by 0x40A38F4: char*
std::string::_S_construct<char*>(char*, char*, std::allocator<char>
const&, std::forward_iterator_t
ag) (basic_string.tcc:154)
==23358== by 0x40A2F84: std::string::string<char*>(char*, char*,
std::allocator<charconst&) (basic_string.h:732)
==23358== by 0x4097959: std::basic_stringbuf<char,
std::char_traits<char>, std::allocator<char::str() const
(stl_alloc.h:664)
==23358== by 0x409A57B: std::basic_ostringstream<char,
std::char_traits<char>, std::allocator<char::str() const (sstream:
301)
==23358== by 0x8048B84: main (in /mgr/shared/home/pwalker/tweb/
tweb_release/trunk/test-ostringstream)
==23358==
==23358==
==23358== 1,136 bytes in 1 blocks are possibly lost in loss record 3
of 3
==23358== at 0x401AD81: operator new(unsigned) (vg_replace_malloc.c:
224)
==23358== by 0x409CB02: std::__default_alloc_template<true,
0>::allocate(unsigned) (stl_alloc.h:109)
==23358== by 0x40A2B67: std::string::_Rep::_S_create(unsigned,
std::allocator<charconst&) (stl_alloc.h:685)
==23358== by 0x40A2C98:
std::string::_Rep::_M_clone(std::allocator<charcon st&, unsigned)
(basic_string.tcc:474)
==23358== by 0x40A0A05: std::string::reserve(unsigned)
(basic_string.h:237)
==23358== by 0x4097C28: std::basic_stringbuf<char,
std::char_traits<char>, std::allocator<char::overflow(int)
(sstream.tcc:103
)
==23358== by 0x409DED3: std::basic_streambuf<char,
std::char_traits<char::xsputn(char const*, int) (char_traits.h:161)
==23358== by 0x40948D0: std::ostream::write(char const*, int)
(streambuf:340)
==23358== by 0x4094FE5: std::basic_ostream<char,
std::char_traits<char& std::operator<< <std::char_traits<char>
>(std::basic_o
stream<char, std::char_traits<char&, char const*) (ostream.tcc:640)
==23358== by 0x8048B6B: main (in /mgr/shared/home/pwalker/tweb/
tweb_release/trunk/test-ostringstream)
==23358==
==23358== LEAK SUMMARY:
==23358== definitely lost: 0 bytes in 0 blocks.
==23358== possibly lost: 2,096 bytes in 2 blocks.
==23358== still reachable: 88 bytes in 1 blocks.
==23358== suppressed: 0 bytes in 0 blocks.
==23358== Reachable blocks (those to which a pointer was found) are
not shown.
==23358== To see them, rerun with: --leak-check=full --show-
reachable=yes
Aborted
================================================== ===========================

If I remove the throw, then valgrind says everything is fine. So my
question is whether this is expected behavior from the throw and if
not, how do I solve it?

TIA
Jul 21 '08 #1
Share this Question
Share on Google+
13 Replies


P: n/a
Pep wrote:
I have recently eradicated a lot of memory leaks in a very old C++
source set. However, whilst they were all fairly easy to resolve, I am
confused by the last one. This seems to be related to throwing a
std::exception with a string object.

This is the test program

================================================== ===========================
#include <sstream>
#include <iostream>
#include <stdlib.h>
#include <stdexcept>

int main(int argc, char** argv)
{
std::ostringstream os;
os << "Test string";
throw std::out_of_range(os.str());

return(0);
}
================================================== ===========================
>
and this is the output from valgrind when I run it
[snip]
>
If I remove the throw, then valgrind says everything is fine. So my
question is whether this is expected behavior from the throw and if
not, how do I solve it?
The following is valgrind-clean on my platform:

#include <sstream>
#include <iostream>
#include <stdlib.h>
#include <stdexcept>

int main(int argc, char** argv)
{
try {
std::ostringstream os;
os << "Test string";
throw std::out_of_range(os.str());
}
catch ( std::exception const & e ) {
std::cerr << "exception propagated into main: "
<< e.what() << "\n";
}
catch ( ... ) {
std::cerr << "unidentified thing caught in main.\n";
}
return(0);
}
Best

Kai-Uwe Bux
Jul 21 '08 #2

P: n/a
The following is valgrind-clean on my platform:
>
#include <sstream>
#include <iostream>
#include <stdlib.h>
#include <stdexcept>

int main(int argc, char** argv)
{
* try {
* * * * std::ostringstream os;
* * * * os << "Test string";
* * * * throw std::out_of_range(os.str());
* }
* catch ( std::exception const & e ) {
* * std::cerr << "exception propagated into main: "
* * * * * * * << e.what() << "\n";
* }
* catch ( ... ) {
* * std::cerr << "unidentified thing caught in main.\n";
* }
* return(0);

}
Does this mean that having an exception thrown without being caught
causes a memory leak ?
Jul 21 '08 #3

P: n/a
kh*******@gmail.com wrote:
Does this mean that having an exception thrown without being caught
causes a memory leak ?
Exceptions should always be caught. If an exception is thrown out of
main(), bad things can happen (at least with some compilers and systems).

(OTOH I find it strange that it would leak anything. The stack should
be unwound normally even if it's the main() function.)
Jul 21 '08 #4

P: n/a
On Jul 21, 7:07 pm, Juha Nieminen <nos...@thanks.invalidwrote:
khalid...@gmail.com wrote:
Does this mean that having an exception thrown without being
caught causes a memory leak ?
Exceptions should always be caught. If an exception is thrown
out of main(), bad things can happen (at least with some
compilers and systems).
Such as? The behavior of an uncaught exception is defined by
the standard, and I'm not aware of any compilers which have
problems in this regard.
(OTOH I find it strange that it would leak anything. The stack
should be unwound normally even if it's the main() function.)
If the exception is not caught, it is unspecified whether the
stack is unwound or not---I think that typically, it isn't, so
you still have the information as to where the exception was
thrown in your core dump.

Of course, under a well behaved operating system, nothing leaks,
even if a process terminates abnormally.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jul 21 '08 #5

P: n/a
On Jul 21, 10:07*am, Juha Nieminen <nos...@thanks.invalidwrote:
khalid...@gmail.com wrote:
Does this mean that having an exception thrown without being caught
causes a memory leak ?
* (OTOH I find it strange that it would leak anything. The stack should
be unwound normally even if it's the main() function.)
The thrown object lives somewhere else outside of any stack frame. (I
am not sure whether this is by the standard, or just an implementation
necessity.) So apparently the OP's platform does not destroy that
object if not caught.

Ali
Jul 21 '08 #6

P: n/a
On 2008-07-21 14:57:50 -0400, ac******@gmail.com said:
On Jul 21, 10:07Â*am, Juha Nieminen <nos...@thanks.invalidwrote:
>khalid...@gmail.com wrote:
>>Does this mean that having an exception thrown without being caught
causes a memory leak ?
>Â* (OTOH I find it strange that it would leak anything. The stack should
be unwound normally even if it's the main() function.)

The thrown object lives somewhere else outside of any stack frame. (I
am not sure whether this is by the standard, or just an implementation
necessity.) So apparently the OP's platform does not destroy that
object if not caught.

Ali
Or valgrind is wrong.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Jul 21 '08 #7

P: n/a
Pep
On Jul 21, 6:07 pm, Juha Nieminen <nos...@thanks.invalidwrote:
khalid...@gmail.com wrote:
Does this mean that having an exception thrown without being caught
causes a memory leak ?

Exceptions should always be caught. If an exception is thrown out of
main(), bad things can happen (at least with some compilers and systems).

(OTOH I find it strange that it would leak anything. The stack should
be unwound normally even if it's the main() function.)
Hey everyone, thanks for the replies.

Firstly, I did not even think about the fact that the test program and
therefore the live one that it is based on, is not catching the thrown
exception. Seems silly now you pointed it out, as the main program
itself should really handle the exception and then send the error
status back to the cli via a return statement.

As to whether valgrind is simply wrong, that is another good question
that I had been toying with myself, yet loathe to mention. It always
seems easier to blame the tools ;) However, I am loading up some more
memory testers on this dev server, so that I should be able to answer
that question soon enough.

Apologies for not mentioning that the dev server in question is RHEL
3.0

Thanks again for the replies, I'll catch the exception and handle it
correctly now.
Jul 22 '08 #8

P: n/a
On 2008-07-22 06:29:01 -0400, Pep <pe**********@yahoo.co.uksaid:
>
As to whether valgrind is simply wrong, that is another good question
that I had been toying with myself, yet loathe to mention. It always
seems easier to blame the tools ;)
Indeed. But in the case of memory testers, it's not uncommon to get
false positives for resources that are managed in peculiar ways by the
runtime library. Exception objects are not like normal objects, and I
wouldn't be surprised if memory testers sometimes get them wrong.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Jul 22 '08 #9

P: n/a
James Kanze wrote:
Of course, under a well behaved operating system, nothing leaks,
even if a process terminates abnormally.
No OS can know if the program created some temporary files which it
intends to delete when it terminates.
Jul 22 '08 #10

P: n/a
On Jul 22, 11:40 pm, Juha Nieminen <nos...@thanks.invalidwrote:
James Kanze wrote:
Of course, under a well behaved operating system, nothing
leaks, even if a process terminates abnormally.
No OS can know if the program created some temporary files
which it intends to delete when it terminates.
Sure it can. Perhaps the most common OS's don't do this, but
they certainly could (and I've used at least one OS which did).
For that matter, it's possible to do so under Unix (but only to
a limited extent).

More generally, of course, you're right in that there will
always be some resources for which it isn't clear whether they
should remain or not. g++ (and probably many other compilers)
has an option to explicitly not delete intermediate files; if
something crashes, they can be very useful for debugging. Is
this a resource leak? I'd say yes, but an intentional one.
For that matter, if I don't catch an exception under Unix, I get
a core dump, which can eat up considerable resources.

Within the context of the original posting, however: if a
program terminates because of an uncaught exception, the system
should recover all of the critical resources, without a stack
walkback, and a stack walkback is likely to destroy resoures,
and above all context, that you want to keep, for debugging
purposes. The standard makes it implementation defined (or
unspecified, I'm not sure) whether there is a stack walkback in
such cases, but from a quality of implementation point of view,
I think not walking back the stack is to be preferred.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Jul 23 '08 #11

P: n/a
On Jul 22, 2:53 pm, Pete Becker <p...@versatilecoding.comwrote:
On 2008-07-22 06:29:01 -0400, Pep <pepaltavi...@yahoo.co.uksaid:
As to whether valgrind is simply wrong, that is another good
question that I had been toying with myself, yet loathe to
mention. It always seems easier to blame the tools ;)
Indeed. But in the case of memory testers, it's not uncommon
to get false positives for resources that are managed in
peculiar ways by the runtime library. Exception objects are
not like normal objects, and I wouldn't be surprised if memory
testers sometimes get them wrong.
More generally, there are really cases where "it depends".
Purify (but probably all of the others as well---I've just not
had the occasion to check) has options to allow masking certain
"errors", because they're intentional (e.g. you don't destruct a
singleton), but the tool has no way of knowing this.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jul 23 '08 #12

P: n/a
James Kanze <ja*********@gmail.comwrites:
On Jul 22, 11:40 pm, Juha Nieminen <nos...@thanks.invalidwrote:
>James Kanze wrote:
Of course, under a well behaved operating system, nothing
leaks, even if a process terminates abnormally.
>No OS can know if the program created some temporary files
which it intends to delete when it terminates.

Sure it can. Perhaps the most common OS's don't do this, but
they certainly could (and I've used at least one OS which did).
For that matter, it's possible to do so under Unix (but only to
a limited extent).
What limit do you see in:

char path[]="/tmp/myappl-XXXXXX";
int fd=mkstemp(path);
if(fd!=-1){
unlink(path);
}

knowing that unix systems implement a garbage collector over /tmp on
each reboot (and sometimes even more often), for the unlikely case
where the program crashes between the mkstemp call and the unlink
call.
--
__Pascal Bourguignon__
Jul 23 '08 #13

P: n/a
Pascal J. Bourguignon wrote:
What limit do you see in:
Other programs can't access it unless you smuggle the open file
descriptor over a socket or something similarly arcane (if supported by
the OS in question).
Jul 23 '08 #14

This discussion thread is closed

Replies have been disabled for this discussion.