Topic: Memory leaks with excepti
Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Sat, 9 Apr 1994 22:42:22 GMT Raw View
In article <1994Mar28.173116.7406@datascope.com> sfc@datascope.com (Steve F. Cipolli (P/M)) writes:
...
>So, as the ARM stands now the only thing not freed is the memory for the
>object itself. Notice I said "freed" not "destructed", the object has
>essentially been destructed (assumming the constructor code handled the
>second issue I described above). What remains is only the "shell" of
>memory to be freed.
>
>Also, I believe many compilers already solve this problem; those that do not
>should. The hole, and the only practical solution are obvious (This is not
>to say the details are not difficult).
The details are not only difficult, but possible intractible.
(No reasonable solution without a language change or extension).
--
JOHN (MAX) SKALLER, INTERNET:maxtal@suphys.physics.su.oz.au
Maxtal Pty Ltd, CSERVE:10236.1703
6 MacKay St ASHFIELD, Mem: SA IT/9/22,SC22/WG21
NSW 2131, AUSTRALIA
Author: chris.smith@ftl.mese.com (Chris Smith)
Date: 31 Mar 94 05:13:00 GMT Raw View
In article <1994Mar28.173800.7471@datascope.com>
sfc@datascope.com (Steve F. Cipolli (P/M)) wrote:
SFC(>: In article <9403242313.AA14745@tdat.ElSegundoCA.NCR.COM> swf@tdat.ElSegun
SFC(>NCR.COM (Stan Friesen) writes:
SFC(>: Somehow I get the feeling that our C++ programs won't get more secure...
SFC(>: Instead of checking the return value of new and calling perhaps a
SFC(>: valid() method of the constructed class, I will now have the knowlegde
SFC(>: that something failed, but don't have the chance to clean up. Setting
SFC(>: the (global) behaviour of new is not acceptable since I'm writing
SFC(>: libraries and don't know what other libraries expect from new.
SFC(>: How to solve this? The only thing I can think of is:
SFC(>: try {
SFC(>: Foo *foo = 0;
SFC(>: foo = new Foo();
SFC(>: if (!foo)
SFC(>: // error recovery
SFC(>: }
SFC(>: catch(X& x) {
SFC(>: delete foo;
SFC(>: }
SFC(>: I would be very glad, if someone would come up with a better solution.
SFC(>Someone has, see the ARM 15.3, the example of the lock and grab_lock classe
SFC(>outline what is referred to as "initialization is acquisition" (I might hav
SFC(>the term backwards).
Well, I'm thrilled that the lock got released. But, what if the class
grab_lock had allocated a char** before it threw the exception?
Does the instance of class lock know how to delete the array, which
is a member of class grab_lock? It appears that the solution is
not the solution to the problem that we describe.
---
. OLX 2.2 . I made it foolproof, but they're making better fools...
Author: chris.smith@ftl.mese.com (Chris Smith)
Date: 31 Mar 94 05:13:00 GMT Raw View
In article <1994Mar28.173116.7406@datascope.com>
sfc@datascope.com (Steve F. Cipolli (P/M)) writes:
SFC(>Chris Smith (chris.smith@ftl.mese.com) wrote:
SFC(>: They also need to consider dynamic allocations that the constructor
SFC(>: had made up to the point of throw. Could be a thorny issue, but if
SFC(>: they were to arrange for the destructor (of the failed object) to be
sfc@datascope.com (Steve F. Cipolli (P/M)) wrote:
SFC(>If you are referring to the sub-objects of the object being constructed,
SFC(>their clean-up is guaranteed. See ARM 15.3 ("An object that is
SFC(>partially constructed will have destructors executed only for its fully
SFC(>constructed sub-objects"). If you are referring to new's in the constructo
SFC(>then this job falls to the programmer. The simpliest way to handle that is
SFC(>by the "Acquisition is initialization" technique outlined in the same secti
SFC(> the ARM (ARM 15.3).
err..hmmm. Maybe I was using terminology that is not familiar. When I
say "dynamic allocations", I mean things that are dynamically allocated,
like on the heap, like through new or malloc(). I commonly refer to
them as "dynamic allocations" because they are allocated dynamically
as the need arises, at the time their size is known. What is the
correct term?
ARM 15.3 is referring to "automatic objects". Automatic objects are
not allocatted through new or malloc(). Their size is known at compile
time, although they may contain pointer members that point to memory
allocated through new or malloc() (the size of the pointers is known).
ARM is clear in stating that the fully constructed instances of these
objects have their destructors called. This is no problem. In fact,
if the sub-objects that are allocated via new or malloc() had their
destructors called, that would be no problem, either. That way,
"rely on the execution of the destructor" in ARM 15.3 would have more
meaning in that it would fit not just the case of "automatic
sub-objects", but also "sub-objects" that are allocated by new or
malloc().
SFC(>So, as the ARM stands now the only thing not freed is the memory for the
SFC(>object itself. Notice I said "freed" not "destructed", the object has
SFC(>essentially been destructed (assumming the constructor code handled the
SFC(>second issue I described above). What remains is only the "shell" of
SFC(>memory to be freed.
PLUS whatever the constructor has allocated through new or malloc().
The case of a vector class should be familiar to most people. The
vector class constructor needs to allocate an array, whose size is
not known at compile time. The only ways I can think of, offhand,
to allocate something like this is new, malloc() or calloc(). I
can (and do) arrange for this array to be deleted when the destructor
is called. But, if the constructor throws an exception after the array
is allocated, the destructor is not called (because the vector object
is not fully constructed), and "the job that falls on the programmer"
is made impossible, in spite of his best efforts. The memory is
allocated and nothing points to it so the programmer has no way of
deleting it. If you are suggesting that "the programmer" is
responsible for tracking the allocations made in the constructor
and deleteing them in the constructor, before throwing
the exception, I would imagine that's what a lot of them are doing.
But only out of desparation. Just because it's the only way,
right now, if the programmer uses exceptions and doesn't want leaks.
The current definition of execeptions IMHO is just like a longjump
out of a function; no chance to clean up.
regards,
chris
---
. OLX 2.2 . Are you into casual sex, or should I dress up?
Author: swf@tdat.ElSegundoCA.NCR.COM (Stan Friesen)
Date: Thu, 24 Mar 94 15:13:32 PST Raw View
In article <1801.363.uupcb@ftl.mese.com>, chris.smith@ftl.mese.com (Chris Smith) writes:
|>
|> hmmm. What about:
|> try {
|> Foo *foo = new Foo();
|> }
|> catch(X& x) {
|> delete foo;
|> }
Nope, won't work. The exception was called inside of operator new,
so the assignment to 'foo' was never done. Therefore, it doesn't
point to any memory to be deleted.
[In fact as written, this code produces undefined results, since
'foo' was never even initialized, and need not be a NULL pointer,
so random memory could be delete'd].
--
swf@elsegundoca.ncr.com sarima@netcom.com
The peace of God be with you.
Author: eedste@teamos43.ericsson.se (Stefan Eissing)
Date: Fri, 25 Mar 1994 13:02:07 GMT Raw View
In article <9403242313.AA14745@tdat.ElSegundoCA.NCR.COM> swf@tdat.ElSegundoCA.NCR.COM (Stan Friesen) writes:
>In article <1801.363.uupcb@ftl.mese.com>, chris.smith@ftl.mese.com (Chris Smith) writes:
>|>
>|> hmmm. What about:
>|> try {
>|> Foo *foo = new Foo();
>|> }
>|> catch(X& x) {
>|> delete foo;
>|> }
>
>Nope, won't work. The exception was called inside of operator new,
>so the assignment to 'foo' was never done. Therefore, it doesn't
>point to any memory to be deleted.
>
>[In fact as written, this code produces undefined results, since
>'foo' was never even initialized, and need not be a NULL pointer,
>so random memory could be delete'd].
Somehow I get the feeling that our C++ programs won't get more secure...
Instead of checking the return value of new and calling perhaps a
valid() method of the constructed class, I will now have the knowlegde
that something failed, but don't have the chance to clean up. Setting
the (global) behaviour of new is not acceptable since I'm writing
libraries and don't know what other libraries expect from new.
How to solve this? The only thing I can think of is:
try {
Foo *foo = 0;
foo = new Foo();
if (!foo)
// error recovery
}
catch(X& x) {
delete foo;
}
I would be very glad, if someone would come up with a better solution.
--
___________________________________________________________________
Stefan Eissing Ericsson Eurolab
eedste@aachen.ericsson.se OSS Design & Market Support
Author: Robert Andrew Ryan <rr2b+@andrew.cmu.edu>
Date: Fri, 25 Mar 1994 13:04:36 -0500 Raw View
Excerpts from netnews.comp.std.c++: 25-Mar-94 Re: Memory leaks with
excepti Stefan Eissing@teamos43. (1502)
> How to solve this? The only thing I can think of is:
> try {
> Foo *foo = 0;
> foo = new Foo();
> if (!foo)
> // error recovery
> }
> catch(X& x) {
> delete foo;
> }
> I would be very glad, if someone would come up with a better solution.
Only your compiler writer can solve this issue. The code above can give
undefined results if a base class of Foo throws an exception from it's
constructor. In this case foo will not be completely constructed and
the delete foo call is unlikely to realize this.
The standard needs to address this issue, and I believe it will.
(Simply because to not address it would be insane.)
-Rob
Author: bill@amber.csd.harris.com (Bill Leonard)
Date: 25 Mar 1994 19:39:59 GMT Raw View
In article <1801.363.uupcb@ftl.mese.com>, chris.smith@ftl.mese.com (Chris Smith) writes:
> The more I read these newsgroups, the more I feel that I'm
> missing some fundamental shortcoming of C++. To me,
> 'delete this' _feels_ like suicide. The object is destroying
> itself. That doesn't model real world (sane) behaviour, to me.
> But there is always a thread going about 'delete this'.
> I always pay close attention to those threads, to see
> if I can find a plausable reason _why_ anybody would
> ever actually need to do that.
> Can anybody straighten me out on this? I have written
> a fair amount of C++ (OOP), but have not found myself in a
> situation where an object needs to delete itself. I
> rarely have trouble determining who should, and at what
> time an object should be deleted.
Suppose you have a C++ object that corresponds to some external "thing",
whose existence is not (totally) under your control. For example, a window
on a graphical display has a somewhat separate existence from your program.
Although your program may be able to make the window disappear, so can
other things (like your X server, or the window manager).
In an OO design, the window "object" is the likely one to receive
notification that the actual window has gone away. In that case, it is
logical for the object to delete itself, since it no longer models anything
real.
This kind of behavior is fairly common in an event-driven programming
model, especially when the C++ objects correspond to external objects that
are at most partly controlled by the program.
--
Bill Leonard
Harris Computer Systems Division
2101 W. Cypress Creek Road
Fort Lauderdale, FL 33309
bill@ssd.csd.harris.com
These opinions and statements are my own and do not necessarily reflect the
opinions or positions of Harris Corporation.
------------------------------------------------------------------------------
"I can do trivial things pretty trivially."
Tom Horsley
------------------------------------------------------------------------------
Author: sfc@datascope.com (Steve F. Cipolli (P/M))
Date: Mon, 28 Mar 1994 17:31:16 GMT Raw View
Chris Smith (chris.smith@ftl.mese.com) wrote:
: In article <1994Mar23.182824.5634@datascope.com>
: sfc@datascope.com (Steve F. Cipolli (P/M)) writes
: SFC(>This problem was discussed in one or more threads, a month or so ago. The
: SFC(>committee I believe will be looking at it soon. The answer will be somethi
: SFC(>like what you described (the objects memory will be freed on throw from
: SFC(>constructor). There are however serveral issues which need to be considere
: They also need to consider dynamic allocations that the constructor
: had made up to the point of throw. Could be a thorny issue, but if
: they were to arrange for the destructor (of the failed object) to be
: called, the programmer could handle that. If they don't provide a
: way for the programmer to ensure that _all_ of the memory for a failed
: constructor is freed, it will still be viewed as less than desirable.
If you are referring to the sub-objects of the object being constructed,
their clean-up is guaranteed. See ARM 15.3 ("An object that is
partially constructed will have destructors executed only for its fully
constructed sub-objects"). If you are referring to new's in the constructor,
then this job falls to the programmer. The simpliest way to handle that is
by the "Acquisition is initialization" technique outlined in the same section of the ARM (ARM 15.3).
So, as the ARM stands now the only thing not freed is the memory for the
object itself. Notice I said "freed" not "destructed", the object has
essentially been destructed (assumming the constructor code handled the
second issue I described above). What remains is only the "shell" of
memory to be freed.
Also, I believe many compilers already solve this problem; those that do not
should. The hole, and the only practical solution are obvious (This is not
to say the details are not difficult).
Stephen Cipolli
Datascope Corp.
These opinions are mine alone.
Author: sfc@datascope.com (Steve F. Cipolli (P/M))
Date: Mon, 28 Mar 1994 17:38:00 GMT Raw View
Stefan Eissing (eedste@teamos43.ericsson.se) wrote:
: In article <9403242313.AA14745@tdat.ElSegundoCA.NCR.COM> swf@tdat.ElSegundoCA.NCR.COM (Stan Friesen) writes:
: >In article <1801.363.uupcb@ftl.mese.com>, chris.smith@ftl.mese.com (Chris Smith) writes:
: >|>
: >|> hmmm. What about:
: >|> try {
: >|> Foo *foo = new Foo();
: >|> }
: >|> catch(X& x) {
: >|> delete foo;
: >|> }
: >
: >Nope, won't work. The exception was called inside of operator new,
: >so the assignment to 'foo' was never done. Therefore, it doesn't
: >point to any memory to be deleted.
: >
: >[In fact as written, this code produces undefined results, since
: >'foo' was never even initialized, and need not be a NULL pointer,
: >so random memory could be delete'd].
: Somehow I get the feeling that our C++ programs won't get more secure...
: Instead of checking the return value of new and calling perhaps a
: valid() method of the constructed class, I will now have the knowlegde
: that something failed, but don't have the chance to clean up. Setting
: the (global) behaviour of new is not acceptable since I'm writing
: libraries and don't know what other libraries expect from new.
: How to solve this? The only thing I can think of is:
: try {
: Foo *foo = 0;
: foo = new Foo();
: if (!foo)
: // error recovery
: }
: catch(X& x) {
: delete foo;
: }
: I would be very glad, if someone would come up with a better solution.
Someone has, see the ARM 15.3, the example of the lock and grab_lock classes
outline what is referred to as "initialization is acquisition" (I might have
the term backwards).
Stephen Cipolli
Datascope Corp.
These opinions are mine alone.
Author: chris.smith@ftl.mese.com (Chris Smith)
Date: 24 Mar 94 05:04:00 GMT Raw View
In article <CBARBER.94Mar22095548@apricot.bbn.com>
cbarber@bbn.com (Christopher Barber) wrote:
CB>Subject: Memory leaks with exception thrown from a new'ed constructor
CB>I am sure that someone has already brought this up at some point,
CB>but just in case....
CB>Is the standards comittee addressing the following hole in the language?
CB>class Foo {
CB>Foo() ;
CB>// ...
CB>};
CB>Foo::Foo()
CB>{
CB>// ...
CB>if (something_bad_happens)
CB>throw X();
CB>}
CB>Foo *foo = new Foo() ;
CB>When Foo() throws the exception, there is now way to delete the storage
CB>that was allocated before the constructor was called.
hmmm. What about:
try {
Foo *foo = new Foo();
}
catch(X& x) {
delete foo;
}
To me, this seems appropriate, as the entity that is responsible
for the object's creation is most likely to need information on
the failure of the creation of the object.
It would also be the most capable candidate for the deletion of the
object, as it knows what the object is, why it was created,
where it is, and the consequences of the failure of its creation.
CB>One could have Foo delete itself prior to throwing:
The more I read these newsgroups, the more I feel that I'm
missing some fundamental shortcoming of C++. To me,
'delete this' _feels_ like suicide. The object is destroying
itself. That doesn't model real world (sane) behaviour, to me.
But there is always a thread going about 'delete this'.
I always pay close attention to those threads, to see
if I can find a plausable reason _why_ anybody would
ever actually need to do that.
Can anybody straighten me out on this? I have written
a fair amount of C++ (OOP), but have not found myself in a
situation where an object needs to delete itself. I
rarely have trouble determining who should, and at what
time an object should be deleted.
I guess followup (to my posting, not the original article), if
any should go to comp.lang.c++.
---
. OLX 2.2 . What's another word for Thesaurus?
Author: bobkf@news.delphi.com (BOBKF@DELPHI.COM)
Date: 24 Mar 1994 14:49:02 -0500 Raw View
Chris Smith writes:
>hmmm. What about:
>try {
>Foo *foo = new Foo();
>}
>catch(X& x) {
>delete foo;
>}
That would be swell if it worked. But if Foo throws an exception while
being constructed, foo will never be set. That's the whole point.
Bob Foster
Object Factory