Topic: When bad things happen to good delete expressions
Author: phalpern@truffle.ma.ultranet.com (Pablo Halpern)
Date: 1997/03/28 Raw View
fjh@mundook.cs.mu.OZ.AU (Fergus Henderson) wrote:
>Gerard Weatherby <gerardw@alum.mit.edu> writes:
>
>>Fergus Henderson wrote:
>>
>>> The current draft doesn't give the implementation any license to modify
>>> `p', so `p' should not be modified; unless otherwise specified,
>>> `delete' doesn't modify its argument, just as `->' and `+' don't modify
>>> their arguments. When reading the draft, you have to presume that the
>>> implementation is not going to arbitrarily modify values in ways not
>>> specified by the draft.
>>
>>How do you intepret "[Note: the value of a pointer that refers to
>>deallocated storage is indeterminate. ]" (from 5.3.5 p.4?)
I interpret the word "indeterminate" to mean "cannot be determined."
Given a statement "delete p;" The note does not say that the value of
the p is indeterminate, only that the value of a pointer to deallocated
storage is indeterminate. If the class-specific operator delete() does
not deallocate the storage, the the value of p is still well-defined.
Even if delete does deallocate the storage, at the end of the
expression, p does not necessarily point to deallocated storage. For
example, look at the following code, where one object automatically
registers and de-registers itself with another object:
class slave;
class master
{
slave *theSlave;
public:
void setSlave(slave *s) { theSlave = s; }
deleteSlave() { delete theSlave; }
// ...
};
class slave
{
master *theMaster;
public:
// Automatically registeres and deregisters itself with its master.
slave(master *m) : theMaster(m) { theMaster->setSlave(this); }
~slave() { theMaster->setSlave(0); }
};
int main()
{
master *m = new master;
slave *s1 = new slave(m);
delete s1;
// s1 is now "indeterminate." m->theSlave is now null.
slave *s2 = new slave(m);
m->deleteSlave();
// s2 now points to deallocated storage.
// What is the value of m->theSlave? !!!
}
In the last line (marked with !!!), my understanding would have
m->theSlave be null. Does the draft standard allow the implementation to
modify the pointer at the end of the delete expression in this case? If
so, then m->theSlave might *not* be null, and the code is broken. This
situation comes up frequently in situations where objects' destructors
remove themselves from vectors, etc.
Given any statement "delete p;" the result of evaluating it successfully
depend on the definition of operator delete() in context (does it
actually deallocate storage?), whether *p has access to p (as in the
example above), whether P is global, and can thus be modified by either
the destructor or operator delete(), etc. Thus, virtually nothing can
be said about the value of p after the statement is executed. Thus, it
can be said that the value of p is "indeterminate." The statement that
deallocating the storage renders the pointer invalid refers, IMHO, to
the original value of the pointer, not to the pointer variable itself.
Thus, I believe that the standard does *not* allow the built-in operator
delete to modifiy its argument unless it can determine that the value of
the argument is definately points to deallocated storage. Using the
"as-if" rule, in those rare cases where it *can* be determined, the
implementation can then replace one bad value with another (better
understood) bad value.
-------------------------------------------------------------
Pablo Halpern phalpern@truffle.ultranet.com
I am self-employed. Therefore, my opinions *do* represent
those of my employer.
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: "Robert DiFalco" <interzone@earthlink.com>
Date: 1997/03/25 Raw View
> Apparently, the ability for an implementation to change the value of 'p'
is
> a feature that used to exist in the language but has been removed in the
> latest draft (although the draft does state that "the value of a pointer
> that refers to deallocated storage is indeterminate"). This requires you
> the programmer to explicitly set 'p' to NULL, otherwise you run the risk
> of having ill-behaved programs.
>
> I said (and still feel) that 'delete p' should set 'p' to NULL implicitly
> (provided that 'p' is a modifiable lvalue). This would ensure that A)
pointer
> 'p' is well-defined rather than indeterminate, and B) subsequent 'delete
p'
> statements would be well-behaved. Some people disagreed, usually in the
> interests of efficiency; others agreed, usually in the interests of
program
> reliability.
>
What if it wasn't a modifiable lvalue? I wouldn't disagree in the interest
of efficiency, but I would in the interest of well-formed code and
consistancy. The very idea of a situation that calls for subsequent
evaluations of 'delete p' seems to indicate code out of control. If you
don't know the state of 'p', then 'p' is indeterminate and shouldn't be
deleted. If you are making subsequent calls to delete, then you *do not*
know the state of 'p'. If the structured call to delete failed, then 'p'
should not be the subject of a subsequent delete statement. I can't think
of a situation where I would want to 'delete p', after a failed attempt. Am
I missing something?
This seems similar to the situation created by an abandoned mutex.
Technically, another thread is allowed to seize control of an abandoned
mutex, but you cannot know whether the mutex was abandoned because it was
simply not released before the thread was normally terminated or abandoned
because an exception caused early retirement of the thread putting the
shared resource into an unknown state. While the shared resource *may* be
in a known state, as would be the case of an implicitly released mutex, you
cannot garuantee this. That a question exists regarding the state of a
shared resource when an abandoned mutex is encountered indicates the lack
of a clear rule that yields a single response to this situation. By simply
creating the rule: "Every explicit seize requires an explicit release",
allows you to take definitive action since you can be sure that an
abandoned mutex indicates a violation of the rule. Whether that is a coding
or execution violation, you follow the rules assuming that the shared
resource is in an unknown state because an abandoned mutex indicates an
error condition. Using this same logic, if 'delete p' fails, you should be
able to assume that 'p' is in an unknown state and should not be the
subject of subsequent calls to delete. Subsequent calls to delete, once
again, indicates code out of control just as 'while ( locked ) unlock()'
indicates code out of control. If you don't know the state of 'locked', you
shouldn't just call 'unlock()' until the object is available. If you don't
know the state of 'lock', at least the currently executing blocks state,
then you have lost control over the flow of logic in your code. This is why
escorts (aka chaparon) or auto_ptr's are so important for new/delete,
alloc/free, seize/release or lock/unlock sorts of schemes.
Robert
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: fjh@murlibobo.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/03/18 Raw View
James Kanze <james-albert.kanze@vx.cit.alcatel.fr> writes:
>Marcelo Cantos <marcelo@mds.rmit.edu.au> writes:
>
>|> > Well, the above quote of mine is a little bit out of context. The
>|> > poster I was responding to was talking about (unusual) cases where
>|> > delete does not actually deallocate the storage. It is true that
>|> > _unless otherwise specified_ delete doesn't modify its argument.
>|> > However, if delete does indeed deallocate the storage, then the value
>|> > of any pointer to it is indeterminate, and any use of such a value
>|> > would result in undefined behaviour.
>|>
>|> There appears to be some confusion about what the term `value' means
>|> when applied to a pointer. The above paragraph implies that `value'
>|> refers to the object pointed to, whereas one would typically expect it
>|> to mean the value that the pointer itself contains.
>
>I didn't read it that way.
No. I was talking only about the value of the pointer, not the value
it points to. The part of the standard I quoted also referred to the
value of the pointer, not the value of the data it points to.
>|> Although the
>|> standard seems to agree with the `object pointed to' interpretation,
I certainly don't read it that way.
>|> otherwise it would indeed be implying that the pointer variable can be
>|> altered by the delete operator of a conforming implementation.
Yes, that's correct. But only if the memory it points to is deallocated.
If the memory it points to is not deallocated (e.g. if the destructor
and/or the `operator delete' function throw an exception, or if the
`operator delete' function is a used-defined operator delete that doesn't
actually deallocate the memory), then the implementation cannot modify the
pointer.
>|> Perhaps it really does mean that so implementations are free to fill
>|> the pointer with zero, rubbish, an error value or whatever for
>|> debugging purposes.
>
>No. What I think Fergus is saying is that:
>
>1. An implementation can do anything it pleases, as long as what it does
>doesn't change the visible behavior of a conforming program. And it can
>do anything it pleases, period, with a non-conforming program.
Yes.
>2. A conforming program cannot access the pointer freed by delete in any
>way what so ever. So if the implementation has trashed it, it cannot
>tell.
Yes.
>3. A program which does access the pointer is not conforming, so the
>implementation can trash the pointer if it likes.
Uh, not quite. As you point out below, an program
can access the value as an array of bytes. However,
such a program can't rely on the value remaining unchanged.
>I'm not 100% sure that Fergus is right. I think that you can read a
>deleted pointer with memcpy, so a conforming program could detect that
>the implementation had trashed the pointer with:
>
> T* p ;
> unsigned char before[ sizeof( T* ) ] ;
> unsigned char after[ sizeof( T* ) ] ;
> std::memcpy( before , &p , sizeof( T* ) ) ;
> delete p ;
> std::memcpy( after , &p , sizeof( T*) ) ;
> assert( std::memcpy( before , after , sizeof( T* ) ) == 0 ) ;
The pointer value after the delete is "indeterminate",
so the assertion may fail.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: aeb@saltfarm.bt.co.uk (Tony Bass)
Date: 1997/03/18 Raw View
>From article <rf5bu8iu6cr.fsf@vx.cit.alcatel.fr>, by James Kanze <james-albert.kanze@vx.cit.alcatel.fr>:
[...]
> No. What I think Fergus is saying is that:
> 1. An implementation can do anything it pleases, as long as what it does
> doesn't change the visible behavior of a conforming program. And it can
> do anything it pleases, period, with a non-conforming program.
> 2. A conforming program cannot access the pointer freed by delete in any
> way what so ever. So if the implementation has trashed it, it cannot
> tell.
> 3. A program which does access the pointer is not conforming, so the
> implementation can trash the pointer if it likes.
> I'm not 100% sure that Fergus is right. I think that you can read a
> deleted pointer with memcpy, so a conforming program could detect that
> the implementation had trashed the pointer with:
[...]
How about self-assignment? The example I have in mind is, suppose an
unordered set of pointer to T is kept in a linear array,
int N;
T *p[100]; // p[0..N-1] are new'd pointers
and one wants to delete and remove from this set the pointer at i, with
the usual algorithm of overwriting it with the last element,
delete p[i];
p[i] = p[--N];
Is this well-defined when i is N-1, or should a careful programmer write
something like
delete p[i];
p[i] = (T *)0;
p[i] = p[--N];
instead?
Tony Bass
--
# Tony Bass Tel: (01473) 645305
# MLB 3/19, BT Laboratories e-mail: aeb@saltfarm.bt.co.uk
# Martlesham Heath, Ipswich, Suffolk, IP5 7RE DO NOT e-mail to From: line
# Opinions are my own
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: fjh@murlibobo.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/03/19 Raw View
aeb@saltfarm.bt.co.uk (Tony Bass) writes:
>How about self-assignment?
Any use of an indeterminate value, including self-assignment, would
constitute undefined behaviour.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: "Paul Black" <paul.black@vf.vodafone.co.uk>
Date: 1997/03/19 Raw View
herbs@cntc.com (Herb Sutter) wrote:
> David R Tribble <david.tribble@central.beasys.com> wrote:
> >I said (and still feel) that 'delete p' should set 'p' to NULL implicitly
> >(provided that 'p' is a modifiable lvalue). This would ensure that A) pointer
> >'p' is well-defined rather than indeterminate, and B) subsequent 'delete p'
> >statements would be well-behaved. Some people disagreed, usually in the
> >interests of efficiency; others agreed, usually in the interests of program
> >reliability.
>
> And I disagreed, with a third option: If you're going to change the value
> anyway, then don't use null! If anything, 'delete p' should set 'p' to a
> known-bad value implicitly. The values 0xbaddf00d (say it out loud) and
> 0xdeadbeef are popular on various platforms.
NULL is a better value than 0xbaddf00d or 0xdeadbeef. If you use these
values then your pointer may end up pointing to memory that is used by
other objects. Accesses through the (dangling) pointer may corrupt these
other objects. Using NULL gives implementations a chance to detect access
to an invalid object. This must be better than having
intermittent/indeterminate behaviour.
Paul
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/19 Raw View
aeb@saltfarm.bt.co.uk (Tony Bass) writes:
No. Accessing p[i] after the delete results in undefined behavior,
regardless of the reasons for the access.
|> or should a careful programmer write
|> something like
|>
|> delete p[i];
|> p[i] = (T *)0;
|> p[i] = p[--N];
|>
|> instead?
Either that, or check for the special case:
delete p[ i ] ;
N -- ;
if ( i < N )
p[ i ] = p[ N ] ;
--
James Kanze home: kanze@gabi-soft.fr +33 (0)1 39 55 85 62
office: kanze@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: herbs@cntc.com (Herb Sutter)
Date: 1997/03/19 Raw View
"Paul Black" <paul.black@vf.vodafone.co.uk> wrote:
>herbs@cntc.com (Herb Sutter) wrote:
>> And I disagreed, with a third option: If you're going to change the value
>> anyway, then don't use null! If anything, 'delete p' should set 'p' to a
>> known-bad value implicitly. The values 0xbaddf00d (say it out loud) and
>> 0xdeadbeef are popular on various platforms.
>
>NULL is a better value than 0xbaddf00d or 0xdeadbeef. If you use these
>values then your pointer may end up pointing to memory that is used by
>other objects. Accesses through the (dangling) pointer may corrupt these
>other objects.
No so, since such an implementation would reserve the "known bad" value and
never use it for real pointers. The point is that if the implementation
changes the pointer to NULL after deletion, as was suggested, it still
can't distinguish between "use of pointer before initialized" and "use of
pointer after deleted" -- for example, in some cases the latter could be
used to detect some double deletes where the first cannot. If the
implementation is going to incur the (minimal) overhead of changing the
pointer value after the delete anyway, then it should at least choose the
option that gives more information.
Note, of course, that with pointer aliasing this still doesn't solve the
general problem of using a pointer after it's been deleted, and that
general problem can't be cheaply solved. What can be cheaply done is to
use this approach to enable better diagnostics for a significant fraction
of access-after-delete problems.
>Using NULL gives implementations a chance to detect access
>to an invalid object.
But it does not let them distinguish between use of an uninitialized
pointer vs. of a stale pointer.
---
Herb Sutter (mailto:herbs@cntc.com)
Current Network Technologies Corp. (http://www.cntc.com)
2695 North Sheridan Way, Suite 150, Mississauga ON Canada L5K 2N6
Tel 416-805-9088 Fax 905-822-3824
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: Marcelo Cantos <marcelo@mds.rmit.edu.au>
Date: 1997/03/20 Raw View
"Paul Black" <paul.black@vf.vodafone.co.uk> writes:
> herbs@cntc.com (Herb Sutter) wrote:
> > And I disagreed, with a third option: If you're going to change the value
> > anyway, then don't use null! If anything, 'delete p' should set 'p' to a
> > known-bad value implicitly. The values 0xbaddf00d (say it out loud) and
> > 0xdeadbeef are popular on various platforms.
>
> NULL is a better value than 0xbaddf00d or 0xdeadbeef. If you use these
> values then your pointer may end up pointing to memory that is used by
> other objects. Accesses through the (dangling) pointer may corrupt these
> other objects. Using NULL gives implementations a chance to detect access
> to an invalid object. This must be better than having
> intermittent/indeterminate behaviour.
No. The implementation can simply make sure that the memory manager
never allocates a block that contains those addresses. This way, if
an attempt is made to read them, a page fault is triggered.
--
______________________________________________________________________
Marcelo Cantos, Research Assistant __/_ marcelo@mds.rmit.edu.au
Multimedia Database Systems Group, RMIT / _ Tel 61-3-9282-2497
723 Swanston St, Carlton VIC 3053 Aus/ralia ><_> Fax 61-3-9282-2490
Acknowledgements: errors - me; wisdom - God; funding - RMIT
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Marcelo Cantos <marcelo@mds.rmit.edu.au>
Date: 1997/03/16 Raw View
fjh@mundook.cs.mu.OZ.AU (Fergus Henderson) writes:
>
> Gerard Weatherby <gerardw@alum.mit.edu> writes:
>
> >Fergus Henderson wrote:
> >
> >> The current draft doesn't give the implementation any license to modify
> >> `p', so `p' should not be modified; unless otherwise specified,
> >> `delete' doesn't modify its argument, just as `->' and `+' don't modify
> >> their arguments. When reading the draft, you have to presume that the
> >> implementation is not going to arbitrarily modify values in ways not
> >> specified by the draft.
> >
> >How do you intepret "[Note: the value of a pointer that refers to
> >deallocated storage is indeterminate. ]" (from 5.3.5 p.4?)
>
> Well, the above quote of mine is a little bit out of context. The
> poster I was responding to was talking about (unusual) cases where
> delete does not actually deallocate the storage. It is true that
> _unless otherwise specified_ delete doesn't modify its argument.
> However, if delete does indeed deallocate the storage, then the value
> of any pointer to it is indeterminate, and any use of such a value
> would result in undefined behaviour.
There appears to be some confusion about what the term `value' means
when applied to a pointer. The above paragraph implies that `value'
refers to the object pointed to, whereas one would typically expect it
to mean the value that the pointer itself contains. Although the
standard seems to agree with the `object pointed to' interpretation,
otherwise it would indeed be implying that the pointer variable can be
altered by the delete operator of a conforming implementation.
Perhaps it really does mean that so implementations are free to fill
the pointer with zero, rubbish, an error value or whatever for
debugging purposes.
In this light the question originally being asked by Scott would be,
what does the standard require (if anything) of a conforming
implementation if the delete fails? (Am I right Scott?)
Could someone please shed some light on this, since I'm getting
awfully confused about what is being discussed.
--
______________________________________________________________________
Marcelo Cantos, Research Assistant __/_ marcelo@mds.rmit.edu.au
Multimedia Database Systems Group, RMIT / _ Tel 61-3-9282-2497
723 Swanston St, Carlton VIC 3053 Aus/ralia ><_> Fax 61-3-9282-2490
Acknowledgements: errors - me; wisdom - God; funding - RMIT
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/17 Raw View
Marcelo Cantos <marcelo@mds.rmit.edu.au> writes:
|> > Well, the above quote of mine is a little bit out of context. The
|> > poster I was responding to was talking about (unusual) cases where
|> > delete does not actually deallocate the storage. It is true that
|> > _unless otherwise specified_ delete doesn't modify its argument.
|> > However, if delete does indeed deallocate the storage, then the value
|> > of any pointer to it is indeterminate, and any use of such a value
|> > would result in undefined behaviour.
|>
|> There appears to be some confusion about what the term `value' means
|> when applied to a pointer. The above paragraph implies that `value'
|> refers to the object pointed to, whereas one would typically expect it
|> to mean the value that the pointer itself contains.
I didn't read it that way.
|> Although the
|> standard seems to agree with the `object pointed to' interpretation,
|> otherwise it would indeed be implying that the pointer variable can be
|> altered by the delete operator of a conforming implementation.
|> Perhaps it really does mean that so implementations are free to fill
|> the pointer with zero, rubbish, an error value or whatever for
|> debugging purposes.
No. What I think Fergus is saying is that:
1. An implementation can do anything it pleases, as long as what it does
doesn't change the visible behavior of a conforming program. And it can
do anything it pleases, period, with a non-conforming program.
2. A conforming program cannot access the pointer freed by delete in any
way what so ever. So if the implementation has trashed it, it cannot
tell.
3. A program which does access the pointer is not conforming, so the
implementation can trash the pointer if it likes.
I'm not 100% sure that Fergus is right. I think that you can read a
deleted pointer with memcpy, so a conforming program could detect that
the implementation had trashed the pointer with:
T* p ;
unsigned char before[ sizeof( T* ) ] ;
unsigned char after[ sizeof( T* ) ] ;
std::memcpy( before , &p , sizeof( T* ) ) ;
delete p ;
std::memcpy( after , &p , sizeof( T*) ) ;
assert( sdt::memcpy( before , after , sizeof( T* ) ) == 0 ) ;
--
James Kanze home: kanze@gabi-soft.fr +33 (0)1 39 55 85 62
office: kanze@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: herbs@cntc.com (Herb Sutter)
Date: 1997/03/17 Raw View
David R Tribble <david.tribble@central.beasys.com> wrote:
>I said (and still feel) that 'delete p' should set 'p' to NULL implicitly
>(provided that 'p' is a modifiable lvalue). This would ensure that A) pointer
>'p' is well-defined rather than indeterminate, and B) subsequent 'delete p'
>statements would be well-behaved. Some people disagreed, usually in the
>interests of efficiency; others agreed, usually in the interests of program
>reliability.
And I disagreed, with a third option: If you're going to change the value
anyway, then don't use null! If anything, 'delete p' should set 'p' to a
known-bad value implicitly. The values 0xbaddf00d (say it out loud) and
0xdeadbeef are popular on various platforms.
---
Herb Sutter (mailto:herbs@cntc.com)
Current Network Technologies Corp. (http://www.cntc.com)
2695 North Sheridan Way, Suite 150, Mississauga ON Canada L5K 2N6
Tel 416-805-9088 Fax 905-822-3824
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Scott Meyers <smeyers@netcom.com>
Date: 1997/03/17 Raw View
Marcelo Cantos wrote:
> In this light the question originally being asked by Scott would be,
> what does the standard require (if anything) of a conforming
> implementation if the delete fails? (Am I right Scott?)
That was my original question, yes, but other postings in this thread
lead me to generalize. Suppose p is the operand of a delete
expression,
delete p;
What do we know about the value of p (not *p, p itself) at the end of
execution of this statement? Does it vary depending on whether an
exception is thrown during execution of the statement?
Scott
----------------------------------------------------------------------------
Scott Meyers, Ph.D. Voice: 503/638-6028
C++ Consulting and Training Fax: 503/638-6614
Author of "Effective C++" Email: smeyers@netcom.com
and "More Effective C++" WWW: http://www.teleport.com/~smeyers
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: Gerard Weatherby <gerardw@alum.mit.edu>
Date: 1997/03/14 Raw View
Fergus Henderson wrote:
> The current draft doesn't give the implementation any license to modify
> `p', so `p' should not be modified; unless otherwise specified,
> `delete' doesn't modify its argument, just as `->' and `+' don't modify
> their arguments. When reading the draft, you have to presume that the
> implementation is not going to arbitrarily modify values in ways not
> specified by the draft.
How do you intepret "[Note: the value of a pointer that refers to
deallocated storage is indeterminate. ]" (from 5.3.5 p.4?)
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/03/15 Raw View
Gerard Weatherby <gerardw@alum.mit.edu> writes:
>Fergus Henderson wrote:
>
>> The current draft doesn't give the implementation any license to modify
>> `p', so `p' should not be modified; unless otherwise specified,
>> `delete' doesn't modify its argument, just as `->' and `+' don't modify
>> their arguments. When reading the draft, you have to presume that the
>> implementation is not going to arbitrarily modify values in ways not
>> specified by the draft.
>
>How do you intepret "[Note: the value of a pointer that refers to
>deallocated storage is indeterminate. ]" (from 5.3.5 p.4?)
Well, the above quote of mine is a little bit out of context. The
poster I was responding to was talking about (unusual) cases where
delete does not actually deallocate the storage. It is true that
_unless otherwise specified_ delete doesn't modify its argument.
However, if delete does indeed deallocate the storage, then the value
of any pointer to it is indeterminate, and any use of such a value
would result in undefined behaviour.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: David R Tribble <david.tribble@central.beasys.com>
Date: 1997/03/15 Raw View
Scott Meyers <smeyers@netcom.com> asked:
> Consider this code:
>
> class Widget { ... };
> Widget *p = new Widget;
> delete p;
>
> Suppose that during execution of "delete p", an exception is thrown,
> either by Widget's destructor or by whatever operator delete that's
> invoked. What do we know about the value of p?
> ...
> Do we have any guarantees at all about the state of p? In particular,
> can we safely delete it again?
This was discussed about a month or two ago on comp.std.c++ by me and others.
Apparently, the ability for an implementation to change the value of 'p' is
a feature that used to exist in the language but has been removed in the
latest draft (although the draft does state that "the value of a pointer
that refers to deallocated storage is indeterminate"). This requires you
the programmer to explicitly set 'p' to NULL, otherwise you run the risk
of having ill-behaved programs.
I said (and still feel) that 'delete p' should set 'p' to NULL implicitly
(provided that 'p' is a modifiable lvalue). This would ensure that A) pointer
'p' is well-defined rather than indeterminate, and B) subsequent 'delete p'
statements would be well-behaved. Some people disagreed, usually in the
interests of efficiency; others agreed, usually in the interests of program
reliability.
Since I can't rely on the implementation, I always set pointers to NULL
after I delete the objects they point to. It's a pain, but this way I know
my pointers are always well-defined. And I've never seen any degradation in
performance caused by the extra instruction or two.
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Scott Meyers <smeyers@netcom.com>
Date: 1997/03/12 Raw View
Consider this code:
class Widget { ... };
Widget *p = new Widget;
delete p;
Suppose that during execution of "delete p", an exception is thrown,
either by Widget's destructor or by whatever operator delete that's
invoked. What do we know about the value of p?
The only thing the standard seems to say is this, from 5.3.5:
4 The cast-expression in a delete-expression shall be evaluated exactly
once. If the delete-expression calls the implementation deallocation
function (_basic.stc.dynamic.deallocation_), and if the operand of the
delete expression is not the null pointer constant, the deallocation
function will deallocate the storage referenced by the pointer thus
rendering the pointer invalid. [Note: the value of a pointer that
refers to deallocated storage is indeterminate. ]
However, if Widget has its own operator delete, this paragraph fails to
apply.
Do we have any guarantees at all about the state of p? In particular,
can we safely delete it again?
Thanks,
Scott
----------------------------------------------------------------------------
Scott Meyers, Ph.D. Voice: 503/638-6028
Software Development Consultant Fax: 503/638-6614
3051 SW Turner Road Email: smeyers@netcom.com
West Linn, Oregon 97068 WWW: http://www.teleport.com/~smeyers
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: "Paul Black" <paul.black@vf.vodafone.co.uk>
Date: 1997/03/12 Raw View
Scott Meyers <smeyers@netcom.com> wrote:
> Consider this code:
>
> class Widget { ... };
>
> Widget *p = new Widget;
>
> delete p;
>
> Suppose that during execution of "delete p", an exception is thrown,
> either by Widget's destructor or by whatever operator delete that's
> invoked. What do we know about the value of p?
It points to an object that no longer exists. The non-trivial destructor
(it must be if it can throw an exception) has started so the lifetime of
the object has ended (section 3.8).
>
> The only thing the standard seems to say is this, from 5.3.5:
>
> 4 The cast-expression in a delete-expression shall be evaluated exactly
> once. If the delete-expression calls the implementation deallocation
> function (_basic.stc.dynamic.deallocation_), and if the operand of the
> delete expression is not the null pointer constant, the deallocation
> function will deallocate the storage referenced by the pointer thus
> rendering the pointer invalid. [Note: the value of a pointer that
> refers to deallocated storage is indeterminate. ]
>
> However, if Widget has its own operator delete, this paragraph fails to
> apply.
>
> Do we have any guarantees at all about the state of p? In particular,
> can we safely delete it again?
Only if it points to a new object. This may happen if an object of the
same type is created at the same storage location (and some other
conditions - section 3.8). The old object can't be deleted again because it
is undefined behaviour to call the destructor for an object whose lifetime has
ended (section 12.4).
Paul
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: fjh@murlibobo.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/03/12 Raw View
Scott Meyers <smeyers@netcom.com> writes:
>Consider this code:
>
> class Widget { ... };
>
> Widget *p = new Widget;
>
> delete p;
>
>Suppose that during execution of "delete p", an exception is thrown,
>either by Widget's destructor or by whatever operator delete that's
>invoked. What do we know about the value of p?
The value should be unchanged.
>The only thing the standard seems to say is this, from 5.3.5: [...]
>However, [...] this paragraph fails to apply.
The current draft doesn't give the implementation any license to modify
`p', so `p' should not be modified; unless otherwise specified,
`delete' doesn't modify its argument, just as `->' and `+' don't modify
their arguments. When reading the draft, you have to presume that the
implementation is not going to arbitrarily modify values in ways not
specified by the draft.
The ARM and earlier drafts did give implementations permission to
modify the value in some cases: "if the expression denoting the
object in a delete expression is a modifiable value, its value
is undefined after the deletion". However this sentence has since been
removed. I presume the reason was because if the memory really is
deallocated, the pointer becomes indeterminate, and its value is
undefined anyway (and thus the sentence would be redundent), and if
the memory is not deallocated, then it is desirable for the pointer
to remain unchanged.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/13 Raw View
Scott Meyers <smeyers@netcom.com> writes:
|> Consider this code:
|>
|> class Widget { ... };
|>
|> Widget *p = new Widget;
|>
|> delete p;
|>
|> Suppose that during execution of "delete p", an exception is thrown,
|> either by Widget's destructor or by whatever operator delete that's
|> invoked. What do we know about the value of p?
|>
|> The only thing the standard seems to say is this, from 5.3.5:
|>
|> 4 The cast-expression in a delete-expression shall be evaluated exactly
|> once. If the delete-expression calls the implementation deallocation
|> function (_basic.stc.dynamic.deallocation_), and if the operand of the
|> delete expression is not the null pointer constant, the deallocation
|> function will deallocate the storage referenced by the pointer thus
|> rendering the pointer invalid. [Note: the value of a pointer that
|> refers to deallocated storage is indeterminate. ]
|>
|> However, if Widget has its own operator delete, this paragraph fails to
|> apply.
|>
|> Do we have any guarantees at all about the state of p? In particular,
|> can we safely delete it again?
Fergus Henderson has addressed the question of p, but what about the
object *p. Can you safely call its destructor again? Consider:
class Widget
{
T1 a ;
T2 b ;
T3 c ;
} ;
The destructor of Widget calls the destructors for c, b and a, in that
order. If the exception is thrown during the destructor of a, b and c
are raw memory, and calling their destructor is almost certainly
undefined behavior.
--
James Kanze home: kanze@gabi-soft.fr +33 (0)1 39 55 85 62
office: kanze@vx.cit.alcatel.fr +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
-- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]