Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Delete a const pointer?

1,252 views
Skip to first unread message

Wilka

unread,
Nov 11, 2000, 3:00:00 AM11/11/00
to
Is this legal C++?

int main()
{
const int* p = new int(10);
delete p;

return 0;
}

MSVC 6.3 says "error C2665: 'delete' : none of the 2 overloads can convert
parameter 1 from type 'const int *'"

I assumed it was another MSVC bug, but according to
http://support.microsoft.com/support/kb/articles/Q131/3/22.asp this is
correct behaviour.


--
- Wilka
(address rot13 encoded)


[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]


Christoph Groth

unread,
Nov 12, 2000, 3:00:00 AM11/12/00
to
"Wilka" <jv...@evghnyvfgvp.pbz> writes:

> Is this legal C++?
>
> int main()
> {
> const int* p = new int(10);
> delete p;
>
> return 0;
> }

Why should deleting a `const int' object on the heap be illegal? g++
has no problems compiling this. Probably yet another one of MSVC's
incompatibilities...

Christoph

Ron Hunsinger

unread,
Nov 13, 2000, 3:00:00 AM11/13/00
to
In article <EKbP5.6356$zJ6.7...@news3.cableinet.net>, "Wilka"
<jv...@evghnyvfgvp.pbz> wrote:

> Is this legal C++?
>
> int main()
> {
> const int* p = new int(10);
> delete p;
>
> return 0;
> }
>

> MSVC 6.3 says "error C2665: 'delete' : none of the 2 overloads can convert
> parameter 1 from type 'const int *'"
>
> I assumed it was another MSVC bug, but according to
> http://support.microsoft.com/support/kb/articles/Q131/3/22.asp this is
> correct behaviour.

Just another case of Microsoft getting it wrong. They say (at the
aforementioned URL) that a pointer to const cannot be deleted, because that
changes the thing pointed to. But what the ISO C++ Standard says is:

[expr.delete] 5.3.5/2:

[Note: a pointer to a const type can be the operand of a
delete-expression; it is not necessary to cast away the
constness (5.2.11) of the pointer expression before it
is used as the operand of the delete-expression. ]

-Ron Hunsinger

Ron Natalie

unread,
Nov 13, 2000, 3:00:00 AM11/13/00
to

Wilka wrote:
>
> Is this legal C++?
>
> int main()
> {
> const int* p = new int(10);
> delete p;
>
> return 0;
> }
>
> MSVC 6.3 says "error C2665: 'delete' : none of the 2 overloads can convert
> parameter 1 from type 'const int *'"


VC++ is wrong. const doesn't apply to delete;

Michael Grove

unread,
Nov 13, 2000, 3:00:00 AM11/13/00
to
it's not legal - p is a pointer to a const int. if you want to be able to
delete p, don't make p a constant pointer. the compiler won't let you
delete
p, because that modifies the data p points to, and this is not allowed
since
you've told the compiler that no one should be able to modify what p points
to.

-mike

Wilka wrote:

> Is this legal C++?
>
> int main()
> {
> const int* p = new int(10);
> delete p;
>
> return 0;
> }
>
> MSVC 6.3 says "error C2665: 'delete' : none of the 2 overloads can
convert
> parameter 1 from type 'const int *'"
>

> I assumed it was another MSVC bug, but according to
> http://support.microsoft.com/support/kb/articles/Q131/3/22.asp this is
> correct behaviour.

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Erik Max Francis

unread,
Nov 13, 2000, 3:00:00 AM11/13/00
to
Wilka wrote:

> Is this legal C++?
>
> int main()
> {
> const int* p = new int(10);
> delete p;
>
> return 0;
> }

It sure is.

> MSVC 6.3 says "error C2665: 'delete' : none of the 2 overloads can
> convert
> parameter 1 from type 'const int *'"
>
> I assumed it was another MSVC bug, but according to
> http://support.microsoft.com/support/kb/articles/Q131/3/22.asp this is
> correct behaviour.

They are incorrect. The C++ Standard, section 5.3.5/2 reads:

[Note: a pointer to a const type can be the operand of a
delete-expression; it is not necessary to cast away the constness
(5.2.11) of the pointer expression before it is used as the operand
of the delete-expression.]

--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, US / 37 20 N 121 53 W / ICQ16063900 / &tSftDotIotE
/ \ God grant me to contend with those that understand me.
\__/ Thomas Fuller
7 sisters productions / http://www.7sisters.com/
Web design for the future.

Ron Natalie

unread,
Nov 13, 2000, 3:00:00 AM11/13/00
to

Michael Grove wrote:
>
> it's not legal - p is a pointer to a const int. if you want to be able to
> delete p, don't make p a constant pointer. the compiler won't let you
> delete
> p, because that modifies the data p points to, and this is not allowed
> since
> you've told the compiler that no one should be able to modify what p points
> to.

The standard does not agree with this. const does not have any affect on
delete.

Carlos Moreno

unread,
Nov 13, 2000, 3:00:00 AM11/13/00
to
Michael Grove wrote:
>
> it's not legal - p is a pointer to a const int. if you want to be able to
> delete p, don't make p a constant pointer. the compiler won't let you
> delete
> p, because that modifies the data p points to, and this is not allowed
> since
> you've told the compiler that no one should be able to modify what p points
> to.

I would like to agree with you -- it does sound strange that delete
is allowed for a pointer to constant -- what action could be more
modifying to an object than deleting it?! And the pointer is actually
stating "you can't use me to modify the object I'm pointing to"

However, if you are forced to drop the constness of every object that
is dynamically allocated, your const correctness would go away. Of
course, it is absolutely scary that you can, for instance, do this:

string s = "....";

delete s.c_str();

And so easily and happily make the program crash! (well, it's not
guaranteed that it will crash, but it is what most likely would happen).

This is one of those vicious circle situations that make you feel so
frustrated...:-(

Carlos
--

Francis Glassborow

unread,
Nov 13, 2000, 3:00:00 AM11/13/00
to
In article <3A0F44E7...@home.com>, Michael Grove
<snow...@home.com> writes

>it's not legal - p is a pointer to a const int. if you want to be able to
>delete p, don't make p a constant pointer. the compiler won't let you
>delete
>p, because that modifies the data p points to, and this is not allowed
>since
>you've told the compiler that no one should be able to modify what p
points
>to.

In a newsgroup with heavy participation by language experts it would
probably be wiser not to post on issues such as this one unless you can
quote chapter and verse to support your belief.

You may find it difficult to accept but deletion is not considered
modification. To give you another example, having write access to a
directory in unix allows you to delete a read only file.

Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

Erik Max Francis

unread,
Nov 13, 2000, 3:00:00 AM11/13/00
to
Carlos Moreno wrote:

> However, if you are forced to drop the constness of every object that
> is dynamically allocated, your const correctness would go away. Of
> course, it is absolutely scary that you can, for instance, do this:
>
> string s = "....";
>
> delete s.c_str();
>
> And so easily and happily make the program crash! (well, it's not
> guaranteed that it will crash, but it is what most likely would
> happen).

I don't really see why this bothers you. You seem to be objecting to
the fact that it's not syntactically incorrect to delete any const
pointer, even ones which you shouldn't. Well, that's true, but that
doesn't make it _correct_; the above fragment, for instance, invokes
undefined behavior because it deletes a pointer that was not returned
from a new.

One can come up with equally contrived situations where you can delete
const-pointers. See:

const int *p = reinterpret_cast<int *>(0xdeadbeef);

delete p;

This is surely syntactically correct, but that doesn't mean it's not
doing something really, really dumb.

As a competent C++ programmer, you have to know what you can delete and
what you can't. Just because a pointer is const doesn't make it fair
game for being deleted (why would it?).

--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, US / 37 20 N 121 53 W / ICQ16063900 / &tSftDotIotE

/ \ Man is a clever animal who behaves like an imbecile.
\__/ Albert Schweitzer
Alcyone Systems' Daily Planet / http://www.alcyone.com/planet.html
A new, virtual planet, every day.

James Kanze

unread,
Nov 14, 2000, 3:00:00 AM11/14/00
to
Francis Glassborow wrote:

> You may find it difficult to accept but deletion is not considered
> modification. To give you another example, having write access to a
> directory in unix allows you to delete a read only file.

I'm not sure the parallel is valid. In the Unix I've worked on, you
can't delete a file. Period. Files are managed by reference counted
pointers, and are deleted automatically by the system when the
reference count drops to zero. All the user can do is delete a
reference, either by deleting a directory entry or closing the file.

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627

Andrew Koenig

unread,
Nov 14, 2000, 3:00:00 AM11/14/00
to
Francis> In article <3A0F44E7...@home.com>, Michael Grove
Francis> <snow...@home.com> writes

Francis> You may find it difficult to accept but deletion is not
Francis> considered modification. To give you another example, having
Francis> write access to a directory in unix allows you to delete a
Francis> read only file.

... and if you couldn't destroy a const object, how could you ever
have a const local variable?

--
Andrew Koenig, a...@research.att.com, http://www.research.att.com/info/ark

Carlos Moreno

unread,
Nov 14, 2000, 3:00:00 AM11/14/00
to
James Kanze wrote:
>
> Francis Glassborow wrote:
>
> > You may find it difficult to accept but deletion is not considered
> > modification. To give you another example, having write access to a
> > directory in unix allows you to delete a read only file.
>
> I'm not sure the parallel is valid.

I agree with this, but for different reasons :-)

The way I see it, you can delete a read-only file (what you're
describing is "implementation details" -- from the practical point
of view, the user deletes the file), but that *does* represent a
violation to the read-only attribute! It's just that the shell
prompts you to confirm the deletion, since it is a read-only
file -- I see this as an analogy with the use of const_cast,
rather than an argument that deleting an object is not modifying
the object.

Carlos
--

Carlos Moreno

unread,
Nov 14, 2000, 3:00:00 AM11/14/00
to
Erik Max Francis wrote:
>
> > string s = "...";
> > delete s.c_str();

>
> I don't really see why this bothers you. You seem to be objecting to
> the fact that it's not syntactically incorrect to delete any const
> pointer, even ones which you shouldn't. Well, that's true, but that
> doesn't make it _correct_; the above fragment, for instance, invokes
> undefined behavior because it deletes a pointer that was not returned
> from a new.

??? How do you know? I'm pretty sure that the standard does not
specify how c_str returns the string. I'm pretty sure that a valid
implementation *is allowed* to return a pointer to its internal copy
of the string (which *may be* allocated with new), or it could create
a duplicate, also allocated with new.

So, maybe in a particular implementation, it may not be allocated
with new, although I don't see how -- other than with malloc (is
that what you were referring to?).

My point was that const is there to protect us (us programmers,
regardless the fact that we are beginners, experienced, or gurus)
from dumb mistakes -- yes, in my example, it is particularly
dumb, because I made it explicit as an example; but we could
accidentally do something like that without noticing, maybe in
a situation where it's not that obvious that the pointer comes
from a call to c_str, or maybe because the name of the variables
are similar and we confused them, etc.

The bottom line is that if we use the argument that "a competent
programmer would not do that", then we might as well end up
dropping the const keyword from the language, arguing that
"a competent programmer would never modify this", or "would
never do that", because it is really dumb to do it.

> As a competent C++ programmer, you have to know what you can delete and
> what you can't.

Yes. But see my argument above. You could extend this to "as a
competent C++ programmer, you have to know what you can modify and
what you can't, and when you can call member functions that modify
and when you can't". So, the const keyword would become useless.

The bottom line of my argument is that, if you accept that deleting
an object is a modifying action (which in my opinion is), then it
does sound scary that you can delete a pointer that points to
something constant (you are indeed using the pointer to perform
an action that modifies the pointee -- however, if you couldn't, then
you would be forced to drop the constness whenever you use dynamic
allocation; that's why I described the situation as sort of a vicious
circle...

Carlos Moreno

unread,
Nov 14, 2000, 3:00:00 AM11/14/00
to
Andrew Koenig wrote:
>
> ... and if you couldn't destroy a const object, how could you ever
> have a const local variable?

This analogy is pretty nice, but I find it a little bit unfair.

A local variable is managed by the compiler, which in most cases
knows what it's doing. Its lifetime expires in a way that is
controlled by the compiler, not by the programmer.

Destroying an object through a pointer is different... The pointer
has a huge sticker saying "don't use me to modify what I'm pointing
to"... So, it is a matter of agreeing on destruction as being a
modifying action or not. I know it's arguable -- even subject to
a philosophical discussion :-) you could say that when you
destroy it, it doesn't exist anymore, thus, it wasn't modified;
it simply ceased to exist, but during its lifetime it wasn't
modified.

On the other hand, the idea of the const is to protect the
program against accidental actions from the programmer (expert
or incompetent). And deleting in a section of code where the
pointer imposes logical constness to the pointee does sound
contradictory to me.

Of course, I still tend to agree with the solution as it is
in the standard (it would be so horrible that you couldn't
set const an object only because it is dynamically allocated,
or that you had to always use const_cast... Maybe this wouldn't
be too much a hassle in exchange for an increased protection
against mistakes...??)

Erik Max Francis

unread,
Nov 15, 2000, 3:00:00 AM11/15/00
to
Carlos Moreno wrote:

> Andrew Koenig wrote:
>
> > ... and if you couldn't destroy a const object, how could you ever
> > have a const local variable?
>
> This analogy is pretty nice, but I find it a little bit unfair.

It's not unfair at all. If deleting a const object is illegal, then no
const objects can be destructed; an object declared const would never
get its destructor called. That's a sad state of affairs if it's tied
to some external resources that it needs to clean up.

--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, US / 37 20 N 121 53 W / ICQ16063900 / &tSftDotIotE

/ \ My heart is pure as the driven slush.
\__/ Tallulah Bankhead


Alcyone Systems' Daily Planet / http://www.alcyone.com/planet.html
A new, virtual planet, every day.

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Wil Evers

unread,
Nov 15, 2000, 3:00:00 AM11/15/00
to
In article <3A116872...@cyberx.com>, Carlos Moreno wrote:

> The bottom line of my argument is that, if you accept that deleting
> an object is a modifying action (which in my opinion is), then it
> does sound scary that you can delete a pointer that points to

> something constant.

This subject was beaten to death on comp.std.c++ last year. If you
like a heated debate, do a quick search for "What const/is was for" on
Dejanews.

- Wil

--
Wil Evers, DOOSYS IT Consultants, Maarssen, Holland
[Wil underscore Evers at doosys dot com]

Dave Nash

unread,
Nov 15, 2000, 3:00:00 AM11/15/00
to
Michael Grove wrote:

> it's not legal - p is a pointer to a const int.

OK, p is a pointer to a constant int

> delete p, don't make p a constant pointer. the compiler won't let you

Wrong, he hasn't made p a constant pointer. A constant pointer is
different from a pointer to a constant.

Dave

> Wilka wrote:

> > const int* p = new int(10);

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

een...@electeng.leeds.ac.uk

unread,
Nov 15, 2000, 3:00:00 AM11/15/00
to
James Kanze <James...@dresdner-bank.de> wrote:
> Francis Glassborow wrote:

>> You may find it difficult to accept but deletion is not considered
>> modification. To give you another example, having write access to a
>> directory in unix allows you to delete a read only file.

> I'm not sure the parallel is valid. In the Unix I've worked on, you


> can't delete a file. Period. Files are managed by reference counted
> pointers, and are deleted automatically by the system when the
> reference count drops to zero. All the user can do is delete a
> reference, either by deleting a directory entry or closing the file.

Surely Francis was talking about file references? Files as you
termed them (ie. the data chunks) don't have access permissions,
do they?

--
Neil

Erik Max Francis

unread,
Nov 15, 2000, 3:00:00 AM11/15/00
to
Carlos Moreno wrote:

> ??? How do you know? I'm pretty sure that the standard does not
> specify how c_str returns the string.

It sure doesn't say you're allowed to delete it.

> I'm pretty sure that a valid
> implementation *is allowed* to return a pointer to its internal copy
> of the string (which *may be* allocated with new), or it could create
> a duplicate, also allocated with new.

It's _allowed_ that std::string::c_str returns a valid pointer created
by new, but what does that have to do with whether or not it's
reasonable for you to delete it manually? In fact, even if what you are
saying is true, undefined behavior would be invoked when the
std::string's destructor double deleted that block.

> So, maybe in a particular implementation, it may not be allocated
> with new, although I don't see how -- other than with malloc (is
> that what you were referring to?).

The Standard says nothing about the allocation or deallocation of the
pointer returned by std::string::c_str, so you've got no business
presuming what it does or does not do.

> My point was that const is there to protect us (us programmers,
> regardless the fact that we are beginners, experienced, or gurus)

> from dumb mistakes ...

It's there to enforce an implicit contract between the interface
designer and the programmer. Object deleting has no part of that
contract.

> Yes. But see my argument above. You could extend this to "as a
> competent C++ programmer, you have to know what you can modify and
> what you can't, and when you can call member functions that modify
> and when you can't". So, the const keyword would become useless.
>

> The bottom line of my argument is that, if you accept that deleting

> an object is a modifying action (which in my opinion is), ...

It cannot be. If so, no object declared as const could ever be
destructed by this argument, including both local and global variables.
Clearly that isn't what const is trying to get at.

--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, US / 37 20 N 121 53 W / ICQ16063900 / &tSftDotIotE

/ \ The believer is happy; the doubter is wise.
\__/ (an Hungarian proverb)


7 sisters productions / http://www.7sisters.com/
Web design for the future.

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

James Kanze

unread,
Nov 15, 2000, 3:00:00 AM11/15/00
to
Carlos Moreno wrote:

> James Kanze wrote:

> > Francis Glassborow wrote:

> > > You may find it difficult to accept but deletion is not
> > > considered modification. To give you another example, having
> > > write access to a directory in unix allows you to delete a read
> > > only file.

> > I'm not sure the parallel is valid.

> I agree with this, but for different reasons :-)

> The way I see it, you can delete a read-only file (what you're
> describing is "implementation details" -- from the practical point
> of view, the user deletes the file), but that *does* represent a
> violation to the read-only attribute! It's just that the shell
> prompts you to confirm the deletion, since it is a read-only file --
> I see this as an analogy with the use of const_cast, rather than an

> argument that deleting an object is not modifying the object.

Well, it wouldn't be the shell which warned you, but rm. And the
warning wasn't (isn't?) always present; when I learned Unix, it
certainly wasn't there.

But the point stands, I think. I agree that what I described are the
"implementation details", although they are fairly well known, since
they are also behind the trick of deleting a temporary file immediatly
after creating it, so that it will disappear even if the process
crashes. The point is that deleting files in Unix works differently
than deleting objects in C++, so it is normal that different rules
apply.

One can imagine logical arguments for both sides. In as far as delete
invokes the destructor, and the destructor is not a const function, I
tend to favor forbidding the delete, but I can understand the other
side's logic. In the end, from my point of view, you can choose one
or the other, so you might as well choose the one which reduces the
probability of programmer error: forbid the deletion.

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627

Carlos Moreno

unread,
Nov 15, 2000, 3:00:00 AM11/15/00
to

Erik,

I think you totally misunderstood what I was trying to say with my
initial comment... I'll try to clarify (although the discussion
may shift into pointless grounds, since -- believe it or not -- we
are agreeing on most things! :-))

Erik Max Francis wrote:
>
> Carlos Moreno wrote:
>
> > ??? How do you know? I'm pretty sure that the standard does not
> > specify how c_str returns the string.
>
> It sure doesn't say you're allowed to delete it.

Of course!!! And my point was that even though the return value
of string::c_str() is a pointer to const, it *can* be deleted
explicitly, invoking undefined behaviour... My point was that
the fact that you can delete a pointer to const does sound
dangerous -- according to the OP's argument, the const in that
return value should prevent you from being able to delete it;
and this was my example to say that what the standard specifies,
though reasonable, does sound scary.

> It's _allowed_ that std::string::c_str returns a valid pointer created
> by new, but what does that have to do with whether or not it's
> reasonable for you to delete it manually?

My point exactly!!! The standard, in this particular example,
is not enforcing the fact that you're *not allowed* to do what
you're not supposed to do (as the const very often enforces)

> In fact, even if what you are
> saying is true, undefined behavior would be invoked when the
> std::string's destructor double deleted that block.

Of course that was exactly my point!! You're not supposed to
delete that manually because in either of the only two possibilities
(either it was allocated with new, in which case it will be deleted
by its owner -- the string object --, or it wasn't allocated by
new, in which case delete will just invoke undefined behaviour).

Notice that it's not that I don't understand what happens or I'm
trying to predict what will happen -- I was using this as an example
of something that you're not supposed to do (and yes, any minimally
competent programmer will know they're not supposed to do it), and
yet the presence of the const in that pointer does not prevent
you from doing it (when *arguably* it should, or it might, given
that destroying an object is *arguably* a modifying action, and
thus should be prohibited by the presence of the const).

The c_str is an example maybe too obvious (I mean, it is too
obvious that you're not supposed to delete it manually), but there
may be tons of similar situations where it would not be that
obvious that you're not supposed to delete a pointer; it would
just be so nice if you had a way to explicitly prohibit such
action.

> The Standard says nothing about the allocation or deallocation of the
> pointer returned by std::string::c_str, so you've got no business
> presuming what it does or does not do.

I wasn't!! You were the one that stated very definitively that
my fragment's undefined behaviour was due to the fact that I wasn't
deleting a pointer allocated with new... (hmmm, although I think
I see what you probably meant... Since *I* didn't explicitly new'ed
that pointer, then I should think of it as if it wasn't allocated
with new, therefore it's not my business to delete it?? Ok, if
you meant that, then 1) I agree, and 2) I misunderstood what you
were saying :-))

> It cannot be. If so, no object declared as const could ever be
> destructed by this argument, including both local and global variables.
> Clearly that isn't what const is trying to get at.

And I said exactly that in my initial message!! I was describing
the situation as a "vicious circle" precisely because of this!!
My point was (and still is) that it would be really nice if we
had a way of returning a pointer to client code and enforcing
the fact that we don't allow them to delete it -- a pointer to
const *may seem* like the way of doing so, if we accept the fact
that destroying an object is considered modifying it (after all,
before deletion, the object was X, and after deletion, the
object is nothing -- nothing is different from X, thus, the
action did modified the object).

But then your above argument (which I mentioned as well) applies:
you wouldn't be able to delete your own constant objects; thus,
you would have to drop the const for every object that is dynamically
allocated...

I hope I clarified what I meant originally (yes, I know that we
still may disagree on the fact that deleting an object is a modifying
action or not -- at least, I think you must agree that the argument
is reasonable, and that both points of view are bound to be defended)

Carlos
--

Carlos Moreno

unread,
Nov 15, 2000, 3:00:00 AM11/15/00
to
Erik Max Francis wrote:
>
> Carlos Moreno wrote:
>
> > Andrew Koenig wrote:
> >
> > > ... and if you couldn't destroy a const object, how could you ever
> > > have a const local variable?
> >
> > This analogy is pretty nice, but I find it a little bit unfair.
>
> It's not unfair at all. If deleting a const object is illegal, then no
> const objects can be destructed

WAIT!! It's not the same... The original point was not "deleting a
const object is illegal"... The original point was "using a pointer
to non-modifiable object to delete it (arguably *modify* it) is illegal"

The original point is wrong, of course -- the standard explicitly says
so; but I insist that the analogy is unfair: one is automatic
destruction
of a const object, managed by the compiler when the lifetime of the
object expires, and the other is managed (possibly irresponsibly) by
the user, via a pointer that is saying not to mdify the object.

Francis Glassborow

unread,
Nov 15, 2000, 3:00:00 AM11/15/00
to
In article <3A116872...@cyberx.com>, Carlos Moreno
<mor...@cyberx.com> writes

>The bottom line is that if we use the argument that "a competent
>programmer would not do that", then we might as well end up
>dropping the const keyword from the language, arguing that
>"a competent programmer would never modify this", or "would
>never do that", because it is really dumb to do it.

That is a C, not C++ argument. In C++ we need to provide different
behaviour for const qualified objects and our ability to overload on
const provides the mechanism we need.

In C++, const is not designed to protect us from stupidity (nothing can
do that, though some languages try to) but to allow us to distinguish
the requirements of read-only items from modifiable ones.
>

Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Carlos Moreno

unread,
Nov 15, 2000, 3:00:00 AM11/15/00
to
James Kanze wrote:
>
> In as far as delete
> invokes the destructor, and the destructor is not a const function, I
> tend to favor forbidding the delete, but I can understand the other
> side's logic. In the end, from my point of view, you can choose one
> or the other, so you might as well choose the one which reduces the
> probability of programmer error: forbid the deletion.

Phew!!! I thought I was completely alone on this!! But I'm glad to
see that at least one experienced programmer shares (100%, I would
say) my point of view... (sure, forbidding the deletion would either
force you to use const_cast always when you (the owner of the allocated
object) delete, or to drop constness for dynamically allocated
objects...
Either way, it would be too bad -- as is too bad that (accidental)
deletion is allowed

Carlos
--

Erik Max Francis

unread,
Nov 15, 2000, 3:00:00 AM11/15/00
to
Dave Nash wrote:

> Wrong, he hasn't made p a constant pointer. A constant pointer is
> different from a pointer to a constant.

The Standard also allows you to delete a constant pointer to T, in
addition to a pointer to constant T. After all, a constant pointer only
means that you can't change its value; deleting the object that it
points to doesn't involve changing that pointer.

--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, US / 37 20 N 121 53 W / ICQ16063900 / &tSftDotIotE

/ \ When you love somebody, you're always in trouble.
\__/ Col. Sherman Potter
Erik Max Francis' bookmarks / http://www.alcyone.com/max/links/
A highly categorized list of Web links.

Manlio Perillo

unread,
Nov 15, 2000, 3:00:00 AM11/15/00
to

"Ron Hunsinger" <hns...@sirius.com> ha scritto nel messaggio
news:hnsngr-ya0231800...@news.flash.net...
> [...]

> But what the ISO C++ Standard says is:
>
> [expr.delete] 5.3.5/2:
>
> [Note: a pointer to a const type can be the operand of a
> delete-expression; it is not necessary to cast away the
> constness (5.2.11) of the pointer expression before it
> is used as the operand of the delete-expression. ]
>


Only a question:

why a destructor cannot be declared const but we
can delete a const pointer?

Regards
Manlio Perillo

Carlos Moreno

unread,
Nov 15, 2000, 3:00:00 AM11/15/00
to
Francis Glassborow wrote:
>
> In C++, const is not designed to protect us from stupidity

Making mistakes is not stupidity -- it's part of our human nature.
Yes, expert programmers make far less mistakes than beginners, but
they still do!

Const does not protect us from *every* mistake that we do; but
there are many situations in which not using the const (or simply
having placed a comment saying that the item should be read-only)
would have left a mistake go unnoticed. And we all know that
mistakes can go unnoticed for very long, even through reasonably
strict Q.A. protocols.

C++, and more in general, the Object Oriented programming approach,
does make a very good job at protecting us from many of our own
mistakes; I wouldn't claim that OOP or C++ protects us from
stupidity, but they do a much better job than, say, C.

Carlos
--

Erik Max Francis

unread,
Nov 15, 2000, 3:00:00 AM11/15/00
to
Carlos Moreno wrote:

> Of course!!! And my point was that even though the return value
> of string::c_str() is a pointer to const, it *can* be deleted
> explicitly, invoking undefined behaviour...

So what? You're not supposed to delete it, not because it's const, but
because you didn't allocate it with new and it's not yours to delete.

The language can't help you from doing stupid things. Trying to delete
a pointer that you have been handed, const or not, is stupid, unless you
know you created the pointer yourself with new or the Standard
explicitly says that it is all right for you to do so.

> My point was that
> the fact that you can delete a pointer to const does sound
> dangerous -- according to the OP's argument, the const in that
> return value should prevent you from being able to delete it;
> and this was my example to say that what the standard specifies,
> though reasonable, does sound scary.

The same exact argument could be applied to non-const pointers. There
are numerous cases where you could be given a _non-const_ pointer that
you're just as certainly not supposed to delete, so the const-ness of
the pointers we're talking about are immaterial. What you've got there
is a red herring.

> My point exactly!!! The standard, in this particular example,
> is not enforcing the fact that you're *not allowed* to do what
> you're not supposed to do (as the const very often enforces)

The fact that you're not supposed to delete the pointer has absolutely
nothing to do with whether or not the pointer is const; you're not
supposed to delete it because it's not yours and you didn't create it
when new.

As such, it is a very poor illustration of the hazards of being able to
delete const pointers, which is what I pointed out.

> Of course that was exactly my point!! You're not supposed to
> delete that manually because in either of the only two possibilities
> (either it was allocated with new, in which case it will be deleted
> by its owner -- the string object --, or it wasn't allocated by
> new, in which case delete will just invoke undefined behaviour).

And that has no bearing on the fact that the pointer is const.

> The c_str is an example maybe too obvious (I mean, it is too
> obvious that you're not supposed to delete it manually), but there
> may be tons of similar situations where it would not be that
> obvious that you're not supposed to delete a pointer; it would
> just be so nice if you had a way to explicitly prohibit such
> action.

Try a better example, then; the std::string::c_str isn't relevant
because you're not supposed to delete it _regardless_ of its constness.
If it had returned a non-const pointer, it would have invoked undefined
behavior to delete it also.

(Note in the above I use "const pointer" and "non-const pointer" to
reference to pointers to const object and pointers to non-const objects,
respectively; from the context of this thread it should have been clear,
but given this isolated post it might not be.)

--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, US / 37 20 N 121 53 W / ICQ16063900 / &tSftDotIotE

/ \ Hell is other people.
\__/ Jean-Paul Sartre
REALpolitik / http://www.realpolitik.com/
Get your own customized newsfeed online in realtime ... for free!

Erik Max Francis

unread,
Nov 15, 2000, 3:00:00 AM11/15/00
to
James Kanze wrote:

> Well, it wouldn't be the shell which warned you, but rm. And the
> warning wasn't (isn't?) always present; when I learned Unix, it
> certainly wasn't there.

It's given by a command line option, -i. Many default shell profiles
alias rm to 'rm -i' to do this for novice users. (Whether it's useful
or not is a totally separate question, and this diversion is already
off-topic for comp.lang.c++.moderated, so I'll stop here.)

> In as far as delete
> invokes the destructor, and the destructor is not a const function, I
> tend to favor forbidding the delete, but I can understand the other
> side's logic.

It is true that destructors are not const functions, but destructors
_cannot_ be declared const, so that is not very relevant. And, in fact,
there's an even bigger indication that this (const destructors) is a red
herring: There are no const _constructors_, either. So does that mean
that no const object should ever be created? Obviously not, so the fact
that destructors can't be const is not relevant, since constructors
can't be either.

Constructors and destructors are _very_ special member functions, and so
const vs. non-const arguments simply don't apply to them.

--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, US / 37 20 N 121 53 W / ICQ16063900 / &tSftDotIotE

/ \ Love is like war: easy to begin but very hard to stop.
\__/ H.L. Mencken


Alcyone Systems' Daily Planet / http://www.alcyone.com/planet.html
A new, virtual planet, every day.

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Ron Hunsinger

unread,
Nov 16, 2000, 3:00:00 AM11/16/00
to
In article <8uup7r$rgj$1...@nslave3.tin.it>, "Manlio Perillo"
<manl...@tin.it> wrote:

> Only a question:
>
> why a destructor cannot be declared const but we
> can delete a const pointer?

Among other things, for symmetry with the constructor. Constructors and
destructors both convert between raw storage and non-const objects.

When you construct a const object, it doesn't become const until the
constructor completes. [Reference: 12.1/4] This makes sense, because the
constructor must be able to modify the object, if for no other reason than
to form it out of raw storage.

[class.ctor] 12.1/4:

A constructor shall not be virtual (10.3) or static (9.4). A
constructor can be invoked for a const, volatile or const volatile
object. A constructor shall not be declared const, volatile, or
const volatile (9.3.2). const and volatile semantics (7.1.5.1) are
not applied on an object under construction. Such semantics only
come into effect once the constructor for the most derived object
(1.8) ends.

By symmetry, a const object reverts to non-const on entry to the
destructor. [Reference 12.4/2] This also makes sense, because a destructor
must also be able to modify the object, if for no other reason than to turn
it back into raw storage.

[class.dtor] 12.4/2:

A destructor is used to destroy objects of its class type. A
destructor takes no parameters, and no return type can be specified
for it (not even void). The address of a destructor shall not be
taken. A destructor shall not be static. A destructor can be invoked
for a const, volatile or const volatile object. A destructor shall
not be declared const, volatile or const volatile (9.3.2). const and
volatile semantics (7.1.5.1) are not applied on an object under
destruction. Such semantics stop being into effect once the destructor
for the most derived object (1.8) starts.

Constructors and destructors also cannot be volatile. The standard is
somewhat vague about what volatile means, but it does say it means the
object may be modified by agents that the compiler does not know about. But
while the object is being constructed or destructed, it is in an
inconsistent state, and such external modifications would probably be
meaningless anyway. The compiler is not required to preserve the
meaningfulness of meaningless modifications.

-Ron Hunsinger

Erik Max Francis

unread,
Nov 16, 2000, 3:00:00 AM11/16/00
to
Manlio Perillo wrote:

> why a destructor cannot be declared const but we
> can delete a const pointer?

I'll answer your question with another question:

Why can a _constructor_ not be declared const but you can create a const
object?

That is to say, constructors and destructors are special member
functions for which const doesn't have a meaning (which doesn't mean
that they are explicitly non-const).

--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, US / 37 20 N 121 53 W / ICQ16063900 / &tSftDotIotE

/ \ The map is not the territory.
\__/ Alfred Korzybski
Esperanto reference / http://mirror/alcyone/max/lang/esperanto/
An Esperanto reference for English speakers.

rado42

unread,
Nov 16, 2000, 3:00:00 AM11/16/00
to
In article <3A1321B3...@alcyone.com>,

So how about a little language extension: making destructors (and
probably constructors, but not nesseccarily) optionally 'const'? It
looks like constructors & desstructors not being const is somewhat
inconsistent with the rest of the language, which causes confusion
sometimes (even for compiler vendors), as this thread shows.

Lacking of 'const' destructor would prevent deleting (and destructing
in other way) a 'const' object. It also gives the possiblity to have 2
destructors: one for 'const', and another for 'normal' objects.

I know it is kinda too late for it and it would break a lot of existing
code, but anyway, I find the idea interesting.

A workaround to keep the existing code compiling would be to threat
dtors to be const by default, and being able to declare them
optionally 'mutable'. An object with only a mutable destructor has to
be mutable (i.e. non-const) in order to be destructed.

And, BTW, I use MSVC60, use const a lot, and have never come to a
situation where I had to delete a 'const' pointer (which MSC60 does not
allow, as someone mentioned). I personally don't like the possibility
to be able to delete a const pointer, although the standard allows it.
Having to do it looks like a design flow to me. So, in this case, I
appreciate the MSVC60 bug - it would expose my design flow.

Last word to the compiler vendors: at least some diagnostics (warning)
when a const pointer is deleted is easily achievable.

Any opitions?

Radoslav Getov


Sent via Deja.com http://www.deja.com/
Before you buy.

Carlos Moreno

unread,
Nov 16, 2000, 3:00:00 AM11/16/00
to

Erik,

Though I agree with most of your arguments, practically all of
them are totally unrelated from what I have been trying to say
(that is, you're still misunderstanding my point)

Erik Max Francis wrote:
>
> Carlos Moreno wrote:
>
> > Of course!!! And my point was that even though the return value
> > of string::c_str() is a pointer to const, it *can* be deleted
> > explicitly, invoking undefined behaviour...
>

> So what? You're not supposed to delete it, not because it's const, but
> because you didn't allocate it with new and it's not yours to delete.

Ok, let's put it this way. Can you assign something (say, with
strcpy) to the characters pointed to by the pointer returned by
string::c_str? Well, you could argue that since the pointer is
not yours, and the standard does not tell you that you're supposed
to modify it, then it would be plain stupidity to do it.

Whether or not stupidity is too strong to describe this, the point
is that you could argue that you can't do such thing regardless of
the fact that the returned pointer points to const.

However, as a class designer, I would prefer to return a pointer
for which I am able to enforce the fact that nobody out there will
be able to use it to modify the data! So, I use const. Yes, const
protects me from other people stupidity and/or mistakes.

PLEASE understand that all I'm trying to say with the example of
string::c_str is the fact that, as a class designer, since I'm
returning a pointer that client code should NEVER delete for any
reason, wouldn't it be just great that I was able to syntactically
prohibit them to do it??

> The language can't help you from doing stupid things.

Oh yes it can!!! We deeply disagree on this one. I'll give you
that the language can't help you from all possible stupid things;
but many stupid things and not-so-stupid mistakes are caught by
the compiler -- and const accounts for some of those situations
where the language protects you from stupidity.

> Trying to delete
> a pointer that you have been handed, const or not, is stupid

And doing strcpy to a pointer that you have been handed this way,
const or not, is stupid. That doesn't mean that it's not a good
idea to cover your back and protect your code against client code's
stupidity.

> The fact that you're not supposed to delete the pointer has absolutely

> nothing to do with whether or not the pointer is const

I know!! That's precisely what the OP was complaining about (well, sort
of), and I partly agree with that argument. My point is that it seems
logical that it should have to do with the fact that is const. The use
of const always is redundant to some other factor. You put const to
the return value of c_str because no client code should modify it.

So, why is it that client code is not supposed to modify it? Because
of the const?? No, because they're not supposed to, period. So, should
that mean that the const is unnecessary there?

> Try a better example, then; the std::string::c_str isn't relevant

> because you're not supposed to delete it _regardless_ of its constness.

Once again, try to understand this: you are not supposed to modify
the characters pointed to by it regardless of its constness. Still,
the const is there helping you, because it enforces the fact that you
will not be able to do something that you're not supposed to do.

The string::c_str argument is relevant if you accept that it all
boils down to the following argument: do we consider delete an action
that modifies the object pointed to by a pointer?? The standard --
and many people -- says NO. Many other people tend to think that yes.

If you accept for a second that deletion is a modifying operation
(just for the sake of the argument, assume for a second that deletion
of a pointer is an action that modifies the pointee), then you would
see that the example of string::c_str is relevant to the original
argument: you are not supposed to delete the pointer returned by
c_str, **regardless of anything**. Now, given that you're not
supposed to do it (because it would be stupid doing so), why not
enforcing it with the use of const, that would prevent deletion
given that it is a modifying operation? (it goes so well with the
idea of "you put const and sleep in peace").

> If it had returned a non-const pointer, it would have invoked undefined
> behavior to delete it also.

I know. But this has nothing to do with my argument. Look at it
this way: writing on an array beyond its capacity invokes undefined
behaviour no matter what, right? However, if that array had been
const, you wouldn't have been able to do it, would you? So, the
fact that undefined behaviour is invoked with or without the const
is no argument to put or not the const.

> (Note in the above I use "const pointer" and "non-const pointer" to
> reference to pointers to const object and pointers to non-const objects,
> respectively; from the context of this thread it should have been clear,
> but given this isolated post it might not be.)

I think it was clear, given the discussion (then again, I've been
following the discussion from the beginning...)

James Kanze

unread,
Nov 17, 2000, 3:00:00 AM11/17/00
to
Erik Max Francis wrote:

> James Kanze wrote:

> > Well, it wouldn't be the shell which warned you, but rm. And the
> > warning wasn't (isn't?) always present; when I learned Unix, it
> > certainly wasn't there.

> It's given by a command line option, -i. Many default shell
> profiles alias rm to 'rm -i' to do this for novice users. (Whether
> it's useful or not is a totally separate question, and this
> diversion is already off-topic for comp.lang.c++.moderated, so I'll
> stop here.)

The -i option causes rm to ask on every file. On the AIX, at least,
the current rm always asks if the file is write protected, whether the
option is given or not.

> > In as far as delete
> > invokes the destructor, and the destructor is not a const function, I
> > tend to favor forbidding the delete, but I can understand the other
> > side's logic.
>
> It is true that destructors are not const functions, but destructors
> _cannot_ be declared const, so that is not very relevant. And, in fact,
> there's an even bigger indication that this (const destructors) is a red
> herring: There are no const _constructors_, either. So does that mean
> that no const object should ever be created? Obviously not, so the fact
> that destructors can't be const is not relevant, since constructors
> can't be either.

> Constructors and destructors are _very_ special member functions,
> and so const vs. non-const arguments simply don't apply to them.

It's certainly not a very strong argument, and it works both ways.
The fact that I can destruct a local const argument is, from what I
understand, the main argument for being able to delete a const.

In the end, for me, the determining factor is which way will cause
less errors. And that would seem to argue for not deleting const.

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627

James Kanze

unread,
Nov 17, 2000, 3:00:00 AM11/17/00
to
een...@electeng.leeds.ac.uk wrote:

> James Kanze <James...@dresdner-bank.de> wrote:
> > Francis Glassborow wrote:

> >> You may find it difficult to accept but deletion is not
> >> considered modification. To give you another example, having
> >> write access to a directory in unix allows you to delete a read
> >> only file.

> > I'm not sure the parallel is valid. In the Unix I've worked on,


> > you can't delete a file. Period. Files are managed by reference
> > counted pointers, and are deleted automatically by the system when
> > the reference count drops to zero. All the user can do is delete
> > a reference, either by deleting a directory entry or closing the
> > file.

> Surely Francis was talking about file references? Files as you
> termed them (ie. the data chunks) don't have access permissions, do
> they?

It depends on the OS. Under Unix, it is the files that have the
access permissions, not the references.

Francis Glassborow

unread,
Nov 17, 2000, 3:00:00 AM11/17/00
to
In article <3A12ED86...@alcyone.com>, Erik Max Francis
<m...@alcyone.com> writes

>The Standard also allows you to delete a constant pointer to T, in
>addition to a pointer to constant T. After all, a constant pointer only
>means that you can't change its value; deleting the object that it
>points to doesn't involve changing that pointer.

You sure about that? Do you know what value is stored in p after:

delete p;

??

Nonetheless, you can delete a const pointer.

>

Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Francis Glassborow

unread,
Nov 17, 2000, 3:00:00 AM11/17/00
to
In article <3A12FD4A...@cyberx.com>, Carlos Moreno
<mor...@cyberx.com> writes

>Francis Glassborow wrote:
>>
>> In C++, const is not designed to protect us from stupidity
>
>Making mistakes is not stupidity -- it's part of our human nature.
>Yes, expert programmers make far less mistakes than beginners, but
>they still do!

However any function that deletes a pointer better be written by someone
who fully understands the implications. This has nothing to do with
const.

Erik Max Francis

unread,
Nov 17, 2000, 3:00:00 AM11/17/00
to
Carlos Moreno wrote:

> PLEASE understand that all I'm trying to say with the example of
> string::c_str is the fact that, as a class designer, since I'm
> returning a pointer that client code should NEVER delete for any
> reason, wouldn't it be just great that I was able to syntactically
> prohibit them to do it??

The way you do that is by documentation. A programmer that deleting
pointers (const or not) willy nilly is going to be trouble to any API
designer. Such a programmer should know that he or she _shouldn't_
delete any pointer he comes across unless the documentation for what
he's using _explicitly_ states that he can. This is true in the
Standard library as much as any other API you might put together.

> > The language can't help you from doing stupid things.
>
> Oh yes it can!!! We deeply disagree on this one. I'll give you
> that the language can't help you from all possible stupid things;
> but many stupid things and not-so-stupid mistakes are caught by
> the compiler -- and const accounts for some of those situations
> where the language protects you from stupidity.

It doesn't make sense to use constness to do this, because constness
means something else.

--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, US / 37 20 N 121 53 W / ICQ16063900 / &tSftDotIotE

/ \ Men live by forgetting -- women live on memories.
\__/ T.S. Eliot
Fat Boy and Little Man / http://www.fatboyandlittleman.com/
Watch Fat Boy and Little Man go about their antics.

bran...@cix.compulink.co.uk

unread,
Nov 17, 2000, 3:00:00 AM11/17/00
to
mor...@cyberx.com (Carlos Moreno) wrote (abridged):

> Phew!!! I thought I was completely alone on this!!

There's me as well. I argued stridently against allowing the delete in
the c.l.s.c++ debate last year.

Here are a few points from that debate which I don't think have yet been
mentioned. The first is that deleting const *was* forbidden by the ARM.
See $5.3.4 for a good explanation of why. Briefly, "The reason is that
the deletion in principle modifies the object pointed to."

Thus the people who think it should be forbidden are in good company, and
the people who thought it is forbidden were right until recently.
Microsoft's compiler used to be correct, and is merely being slow in
tracking changes made by the ISO standard.

In last year's debate, the main practical reason given for allowing the
delete concerned templates. In a template, you may not know whether a
typename argument is const or not. The ISO rule thus makes templates
easier to write.

However, this difficulty is not insurmountable. Several idioms were
presented. I believe we showed every template that could be written with
the ISO rule could also be written, with minor changes, with the stricter
ARM rule. (One especially interesting idiom was a kind of const auto_ptr,
which stored a non-const pointer internally so it could delete it, but
exposed it as const so no-one else could call the object's non-const
methods.)

The debate did not end with consensus. People felt strongly on both
sides.

Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
bran...@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."

Carlos Moreno

unread,
Nov 17, 2000, 3:00:00 AM11/17/00
to
Francis Glassborow wrote:
>
> In article <3A12ED86...@alcyone.com>, Erik Max Francis
> <m...@alcyone.com> writes
> >The Standard also allows you to delete a constant pointer to T, in
> >addition to a pointer to constant T. After all, a constant pointer only
> >means that you can't change its value; deleting the object that it
> >points to doesn't involve changing that pointer.
>
> You sure about that? Do you know what value is stored in p after:
>
> delete p;
>
> ??

In C, with free(p), the answer to your question used to be trivial :-)

> Nonetheless, you can delete a const pointer.

So, this tells me that surely, delete does not change the value of
the pointer (as we should all expect -- of course, since delete is an
operator, and not a function that receives the pointer by value, your
remark is reasonable).

Carlos
--

Carlos Moreno

unread,
Nov 17, 2000, 3:00:00 AM11/17/00
to
Francis Glassborow wrote:
>
> In article <3A12FD4A...@cyberx.com>, Carlos Moreno
> <mor...@cyberx.com> writes
> >Francis Glassborow wrote:
> >>
> >> In C++, const is not designed to protect us from stupidity
> >
> >Making mistakes is not stupidity -- it's part of our human nature.
> >Yes, expert programmers make far less mistakes than beginners, but
> >they still do!
>
> However any function that deletes a pointer better be written by someone
> who fully understands the implications.

Well, and that's the case for anything. Any member function that
modifies the object better be written by someone who understands
the implications; any function that modifies the data pointed
to by a pointer better be written by someone who understands the
implications, etc.

But that doesn't mean that the const should not be used. Someone,
even understanding the implications of everything they do, could
still mistype something, or simply confuse the names of two variables
or parameters (by simple distraction), and introduce a serious bug
in the code. If such action violates a const, then the compiler
is there to tell you!!

> This has nothing to do with
> const.

Of course. Because the standard says that const means something
else. But the thing is that it seems reasonable that const could
(should?) have that meaning too, as Visual C++ mistakenly thinks
(that's the argument being debated; well, at least that's what I've
been trying to debate...)

The "mistakenly" means that Visual C++ is behaving in a way that
contradicts an explicit standard specification. But the point
being that if even a compiler manufacturer thought that const
should have that meaning, that tells you that at least it is
a reasonable point of view (notice how the standard phrases
that item -- it even bothers to put a note explicitly clarifying
that you can delete a pointer to const, that you do not need to
use const_cast to do that; if it was that obvious that const
has nothing to do with deletion of a pointer to const, they
probably wouldn't have bothered to clarify it so explicitly!)

Carlos Moreno

unread,
Nov 17, 2000, 3:00:00 AM11/17/00
to
Erik Max Francis wrote:
>
> [ ... deleting a pointer to const .... ]

>
> It doesn't make sense to use constness to do this, because constness
> means something else.

A-ha!! Finally our discussion came back to the original point! :-)

See? This is exactly the point where we disagree. You, and many
others -- including the standard -- say that const means something
else. That's a fact (because the standard says so). But others,
including myself, think that constness should affect deletion via
a pointer (don't make me wrong: I'm not saying that the standard
should be changed, or even disagreeing with it; it's just that I
do feel that, as James said, both points of view concerning the
validity of deleting a const to pointer are reasonable enough, so
why not favouring the one that prevents mistakes, even if these
are due to plain stupidity?)

Francis Glassborow

unread,
Nov 17, 2000, 3:00:00 AM11/17/00
to
In article <3A137C74...@cyberx.com>, Carlos Moreno
<mor...@cyberx.com> writes

>The string::c_str argument is relevant if you accept that it all
>boils down to the following argument: do we consider delete an action
>that modifies the object pointed to by a pointer?? The standard --
>and many people -- says NO. Many other people tend to think that yes.

Let me tackle this from a slightly different direction. If you see that
an object is not const you deduce that it is OK for you to modify it.
IOWs the absence of const qualification is important information. Now if
you consider that destruction is modification, does that mean that it is
OK to delete any and all objects that you are provided non-const access
to via a pointer? Of course not. The lack of const qualification says
nothing about the correctness of destroying the object, so why should
its presence mean anything?

Rule 1: You do not delete objects that you are not responsible for.
Rule 2: You do not change objects that are qualified as const
Rule 3: You may change that are not const qualified


To repeat, lack of const qualification means that the owner has
implicitly granted you permission to change the object.


Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Erik Max Francis

unread,
Nov 17, 2000, 3:00:00 AM11/17/00
to
Francis Glassborow wrote:

> You sure about that? Do you know what value is stored in p after:
>
> delete p;
>
> ??

The Standard (5.3.5/4) states that afterwards its value is
indeterminate. It certainly doesn't say that it _must_ modify it,
however.

--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, US / 37 20 N 121 53 W / ICQ16063900 / &tSftDotIotE

/ \ I'll be your strength / I'll be here when you wake up (all right)
\__/ Sweetbox
Kepler's laws / http://www.alcyone.com/max/physics/kepler/
A proof of Kepler's laws.

Erik Max Francis

unread,
Nov 17, 2000, 3:00:00 AM11/17/00
to
Carlos Moreno wrote:

> Francis Glassborow wrote:
>
> > However any function that deletes a pointer better be written by
> > someone
> > who fully understands the implications.
>
> Well, and that's the case for anything. Any member function that
> modifies the object better be written by someone who understands
> the implications; any function that modifies the data pointed
> to by a pointer better be written by someone who understands the
> implications, etc.

And that's what demonstrates your scenario to be a red herring. A
programmer that deletes pointers passed to him is a troublemaker;
regardless of whether those are pointers to const or non-const data.

--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, US / 37 20 N 121 53 W / ICQ16063900 / &tSftDotIotE

/ \ The work of many cannot be done alone.
\__/ (a Bemba proverb)
Alcyone Systems / http://www.alcyone.com/
Alcyone Systems, San Jose, California.

Erik Max Francis

unread,
Nov 17, 2000, 3:00:00 AM11/17/00
to
Carlos Moreno wrote:

> See? This is exactly the point where we disagree. You, and many
> others -- including the standard -- say that const means something
> else. That's a fact (because the standard says so).

By definition.

> But others,
> including myself, think that constness should affect deletion via
> a pointer (don't make me wrong: I'm not saying that the standard
> should be changed, or even disagreeing with it; it's just that I
> do feel that, as James said, both points of view concerning the
> validity of deleting a const to pointer are reasonable enough, so
> why not favouring the one that prevents mistakes, even if these
> are due to plain stupidity?)

But throughout this thread I've made several points that demonstrate
other inconsistencies with that worldview and the way C++ works.

Here's just one: If pointers to const objects should not be deleted,
then no const object could ever be destructed. That is clear nonsense.
Therefore that view cannot be consistent with the rest of C++.

--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, US / 37 20 N 121 53 W / ICQ16063900 / &tSftDotIotE

/ \ Defeat is a school in which truth always grows strong.
\__/ Henry Ward Beecher
Polly Wanna Cracka? / http://www.pollywannacracka.com/
The Internet resource for interracial relationships.

Andrew Koenig

unread,
Nov 17, 2000, 3:00:00 AM11/17/00
to
Carlos> Francis Glassborow wrote:

>> You sure about that? Do you know what value is stored in p after:

>> delete p;

>> ??

Carlos> In C, with free(p), the answer to your question used to be trivial
:-)

Really? In C, after free(p), you cannot be assured even of being
able to copy the value of p without your program crashing.
The same is true of C++.

--
Andrew Koenig, a...@research.att.com, http://www.research.att.com/info/ark

Carlos Moreno

unread,
Nov 18, 2000, 3:00:00 AM11/18/00
to

Andrew Koenig wrote:
>
> Carlos> In C, with free(p), the answer to your question used to be trivial
>:-)
>
> Really? In C, after free(p), you cannot be assured even of being
> able to copy the value of p without your program crashing.

??? You totally got me on this one... I have absolutely no clue of
what you're referring to. Still, I trust you, of course :-)

What I'm having trouble to understand is the following: free is a
function, that receives its parameter by value. So, how could that
function do anything to *the value* of that parameter??

Of course, the pointer, after calling free, is non-dereferenceable,
but that has nothing to do with *the value* of p, which I don't
see how could not remain unchanged, or how using it (as in using
its value *without dereferencing it*) could be any trouble.

Could you please clarify?

Carlos
--

Carlos Moreno

unread,
Nov 18, 2000, 3:00:00 AM11/18/00
to

Erik Max Francis wrote:
>
> But throughout this thread I've made several points

And ignored mine! :-)

> Here's just one: If pointers to const objects should not be deleted,
> then no const object could ever be destructed.

I'll assume you meant no const object allocated dynamically could
ever be destructed (const auto objects would not be affected by
the fact that using delete with a pointer to const were prohibited)

> That is clear nonsense.
> Therefore that view cannot be consistent with the rest of C++.

See? Funny how you've been ignoring what I've said no less than
twice during my previous posts.

BTW, strictly speaking, that statement is false. Const objects
would be destructible in that case, by using const_cast (notice
how the standard specifies something along the lines "it is not
necessary to use const_cast to delete a pointer to const").

Gabriel Dos_Reis

unread,
Nov 18, 2000, 3:00:00 AM11/18/00
to
Carlos Moreno <mor...@cyberx.com> writes:

| Andrew Koenig wrote:
| >
| > ... and if you couldn't destroy a const object, how could you ever
| > have a const local variable?
|
| This analogy is pretty nice, but I find it a little bit unfair.
|
| A local variable is managed by the compiler, which in most cases
| knows what it's doing. Its lifetime expires in a way that is
| controlled by the compiler, not by the programmer.

Who ever controls the lifetime needs to invoke the destructor, which
is not a "const function".

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

Pierre Baillargeon

unread,
Nov 18, 2000, 3:00:00 AM11/18/00
to
James Kanze wrote:
>
> In the end, for me, the determining factor is which way will cause
> less errors. And that would seem to argue for not deleting const.
>

But then my brother wrote:
>
> I flag functions pointer arguments that can be deleted with volatile.
> I think that is a strong argument for only allowing the deletion of
> volatile pointers.

My cousin cut in with:
>
> All my functions that receives pointers and are allowed to delete it
> have a name ending with _allowed_to_delete. I think only pointers inside
> functions that ends with _allowed_to_delete should be allowed to be
> deleted.

Which prompted my sister-in-law to say:
>
> I never delete references. So I think it should be forbidden to take
> the address of a reference and delete it.


Should we go on? How about forbiding coding standards that twist the
meaning of const? If you don't want a pinter to be deleted, wrap it in a
smart pointer class.

Note: I'm not implying that I'm related to James Kanze.

Artur Biesiadowski

unread,
Nov 18, 2000, 3:00:00 AM11/18/00
to
Andrew Koenig wrote:

> Carlos> In C, with free(p), the answer to your question used to be trivial
>:-)
>
> Really? In C, after free(p), you cannot be assured even of being
> able to copy the value of p without your program crashing.

> The same is true of C++.

What ????

So if I'll do the following (with p being pointer to structure/object
allocated elsewhere)

long l = (long)p;
free(p);
void * ptr = (void *)l;

I can crash a program ??? I doubt. And having
free(p);
void *ptr = p;
is exactly the same - just copying a integer.

I think that you have mistaken a 'value of p' with 'value pointed to by
p'. There is nothing with pointer aritmetic that could crash anything,
as long as you do not actually use this pointer to dereference anything.

Artur

Sergey P. Derevyago

unread,
Nov 18, 2000, 3:00:00 AM11/18/00
to
Andrew Koenig wrote:
> Carlos> In C, with free(p), the answer to your question used to be trivial
>:-)
>
> Really? In C, after free(p), you cannot be assured even of being
> able to copy the value of p without your program crashing.
> The same is true of C++.
>
Hmm. Did you say that the following snippet of code may crash my program?

int r=rand();
void* p=reinterpret_cast<void*>(r);
cout<<p;

How?
--
With all respect, Sergey. http://cpp3.virtualave.net/
mailto : ders at skeptik.net

Francis Glassborow

unread,
Nov 18, 2000, 3:00:00 AM11/18/00
to
In article <3A155458...@cyberx.com>, Carlos Moreno
<mor...@cyberx.com> writes

>So, this tells me that surely, delete does not change the value of
>the pointer (as we should all expect -- of course, since delete is an
>operator, and not a function that receives the pointer by value, your
>remark is reasonable).

But the Standard explicitly says otherwise. The value of p after
delete p is indeterminate.


Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Gabriel Dos_Reis

unread,
Nov 18, 2000, 3:00:00 AM11/18/00
to
Erik Max Francis <m...@alcyone.com> writes:

| Francis Glassborow wrote:
|
| > You sure about that? Do you know what value is stored in p after:
| >
| > delete p;
| >
| > ??
|

| The Standard (5.3.5/4) states that afterwards its value is
| indeterminate. It certainly doesn't say that it _must_ modify it,
| however.

But it *can*. That was Francis' point.

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Walt Howard

unread,
Nov 18, 2000, 3:00:00 AM11/18/00
to
You might argue:

oktodel: If deleting a pointer to const is illegal because it alters a
const then constructing a const should be illegal also!

notoktodel: Yes, but, without an object constructed, this whole
discussion is moot. There is nothing there to check against const.

oktodel: Aaaaah. Well, with the destructor, the object is already
deleted before the const check is applied so therefore there is
nothing there to check against const.

Walt Howard

James Kanze <James...@dresdner-bank.de> writes:

> In the end, for me, the determining factor is which way will cause
> less errors. And that would seem to argue for not deleting const.

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Gabriel Dos_Reis

unread,
Nov 18, 2000, 3:00:00 AM11/18/00
to
Carlos Moreno <mor...@cyberx.com> writes:

| Francis Glassborow wrote:
| >
| > In article <3A12ED86...@alcyone.com>, Erik Max Francis
| > <m...@alcyone.com> writes


| > >The Standard also allows you to delete a constant pointer to T, in
| > >addition to a pointer to constant T. After all, a constant pointer
only
| > >means that you can't change its value; deleting the object that it
| > >points to doesn't involve changing that pointer.
| >

| > You sure about that? Do you know what value is stored in p after:
| >
| > delete p;
| >
| > ??
|

| In C, with free(p), the answer to your question used to be trivial :-)

Which is?

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Erik Max Francis

unread,
Nov 18, 2000, 3:00:00 AM11/18/00
to
Gabriel Dos_Reis wrote:

> Erik Max Francis <m...@alcyone.com> writes:
>

> > The Standard (5.3.5/4) states that afterwards its value is
> > indeterminate. It certainly doesn't say that it _must_ modify it,
> > however.
>
> But it *can*. That was Francis' point.

I agree that it can. My point (that Francis was originally was
responding to) was that there was no fundamental requirement for delete
p; to modify the contents of p to do its job.

He's absolutely right the Standard says that it _could_. My point was
that it does not _have_ to, so deleting a const pointer to T (rather
than a pointer to const T, what this discussion has primarily been
concerned with) does not have the same sticky issues.

--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, US / 37 20 N 121 53 W / ICQ16063900 / &tSftDotIotE

/ \ Moral indignation is jealousy with a halo.
\__/ H.G. Wells
Product's Quake III Arena Tips / http://www.bosskey.net/
Tips and tricks from the absolute beginner to the Arena Master.

Carlos Moreno

unread,
Nov 18, 2000, 3:00:00 AM11/18/00
to

Walt Howard wrote:
>
> You might argue:
>
> oktodel: If deleting a pointer to const is illegal because it alters a
> const then constructing a const should be illegal also!
>
> notoktodel: Yes, but, without an object constructed, this whole
> discussion is moot. There is nothing there to check against const.
>
> oktodel: Aaaaah. Well, with the destructor, the object is already
> deleted before the const check is applied so therefore there is
> nothing there to check against const.

You have to accept that both points of view are reasonable; you
explained very well that point of view (if an object ceases to
exist, then it was not modified, it simply doesn't exist anymore,
so talking about the object having a different contents doesn't
make sense).

On the other hand, the thing is that if you have p defined as

const T * p;

That means that *p may not be modified. Now, before `delete p',
*p is X (some specific value). After executing `delete p', *p
is nothing (well, it is indeterminate, but we could reasonably
accept that it is "nothing").

So, since X is not equal to "nothing", then the effect of the
statement `delete p' did modify *p, didn't it?

Carlos
--

James Dennett

unread,
Nov 18, 2000, 3:00:00 AM11/18/00
to
Artur Biesiadowski wrote:
>
> Andrew Koenig wrote:
>
> > Carlos> In C, with free(p), the answer to your question used to be trivial
> >:-)
> >

> > Really? In C, after free(p), you cannot be assured even of being
> > able to copy the value of p without your program crashing.
> > The same is true of C++.
>
> What ????
>
> So if I'll do the following (with p being pointer to structure/object
> allocated elsewhere)
>
> long l = (long)p;
> free(p);
> void * ptr = (void *)l;
>
> I can crash a program ??? I doubt. And having
> free(p);
> void *ptr = p;
> is exactly the same - just copying a integer.
>
> I think that you have mistaken a 'value of p' with 'value pointed to by
> p'. There is nothing with pointer aritmetic that could crash anything,
> as long as you do not actually use this pointer to dereference anything.

I suspect that the confusion didn't belong to Mr Koenig. He refers to
systems with hardware which can signal an error if an invalid address
(one
which doesn't point to an object) is loaded into an address register, as
is likely to happen if you attempt to copy the _value_ of a pointer
which
has just been deleted/freed.

I've never worked on such a system, nor do I know of the existence of
such
a beast, but I can imagine that it might be useful in tracking down
errors
in code which did sloppy manipulation of raw pointers.

-- James Dennett <jden...@acm.org>

James Dennett

unread,
Nov 19, 2000, 12:02:59 AM11/19/00
to
Carlos Moreno wrote:
>
> Andrew Koenig wrote:
> >
> > Carlos> In C, with free(p), the answer to your question used to be trivial
> >:-)
> >
> > Really? In C, after free(p), you cannot be assured even of being
> > able to copy the value of p without your program crashing.
>
> ??? You totally got me on this one... I have absolutely no clue of
> what you're referring to. Still, I trust you, of course :-)

But, should you? Argument by authority is always suspicious. And who
is
this shady Koenig person anyway? I don't think that you can rely on
anyone
who goes by the slang name given to a form of naming lookup in C++.
Clearly
a prank post.

For anyone looking for a smilie, I'll recycle the one Carlos sent to the
group.

:-)

There, that was cut+pasted, not typed. Trust me.

Sergey P. Derevyago

unread,
Nov 19, 2000, 3:00:00 AM11/19/00
to
Francis Glassborow wrote:
> In article <3A155458...@cyberx.com>, Carlos Moreno
> <mor...@cyberx.com> writes
> >So, this tells me that surely, delete does not change the value of
> >the pointer (as we should all expect -- of course, since delete is an
> >operator, and not a function that receives the pointer by value, your
> >remark is reasonable).
>
> But the Standard explicitly says otherwise. The value of p after
> delete p is indeterminate.
>
IMHO not exact. Let's take a look at 5.3.5 - Delete [expr.delete], p.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.]

The note is quite confusing: if the value of a pointer is indeterminate
how we
can say that the pointer refers to a deallocated storage?!
And if delete is allowed to change the pointer why it doesn't set the
pointer
to 0? IMHO it'll be quite reasonable.


--
With all respect, Sergey. http://cpp3.virtualave.net/
mailto : ders at skeptik.net

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Sergey P. Derevyago

unread,
Nov 19, 2000, 3:00:00 AM11/19/00
to
James Dennett wrote:

> Artur Biesiadowski wrote:
> > long l = (long)p;
> > free(p);
> > void * ptr = (void *)l;
> >
> > I can crash a program ??? I doubt. And having
> > free(p);
> > void *ptr = p;
> > is exactly the same - just copying a integer.
> >
> > I think that you have mistaken a 'value of p' with 'value pointed to by
> > p'. There is nothing with pointer aritmetic that could crash anything,
> > as long as you do not actually use this pointer to dereference
anything.
>
> I suspect that the confusion didn't belong to Mr Koenig.
:)

> He refers to
> systems with hardware which can signal an error if an invalid address
> (one
> which doesn't point to an object) is loaded into an address register, as
> is likely to happen if you attempt to copy the _value_ of a pointer
> which
> has just been deleted/freed.

I see no necessity in a loading any values in special address registers if
you
are not going to dereference the pointer. BTW a copying of a pointer
through a
special address register seems to be (at least :) nonoptimal.

> I've never worked on such a system, nor do I know of the existence of
> such
> a beast, but I can imagine that it might be useful in tracking down
> errors
> in code which did sloppy manipulation of raw pointers.

IMHO just a copying of any pointers should _never_ crash a program.

Mark Williams

unread,
Nov 19, 2000, 3:00:00 AM11/19/00
to
In article <J0+Xh4Aq...@ntlworld.com>,

Francis Glassborow <fran...@robinton.demon.co.uk> wrote:
> In article <3A155458...@cyberx.com>, Carlos Moreno
> <mor...@cyberx.com> writes
> >So, this tells me that surely, delete does not change the value of
> >the pointer (as we should all expect -- of course, since delete is an
> >operator, and not a function that receives the pointer by value, your
> >remark is reasonable).
>
> But the Standard explicitly says otherwise. The value of p after
> delete p is indeterminate.

Not true. The value of p cannot be used as a pointer. The value of p
*can* be copied to an array of char.

char tmp1[sizeof(p)], tmp2[sizeof(p)];
memcpy(&p, tmp1, sizeof(p));
delete p;
memcpy(&p, tmp2, sizeof(p));
assert(memcmp(tmp1, tmp2, sizeof(p)));

-------------
Mark Williams


Sent via Deja.com http://www.deja.com/
Before you buy.

Walt Howard

unread,
Nov 19, 2000, 3:00:00 AM11/19/00
to
Carlos Moreno <mor...@cyberx.com> writes:

> Walt Howard wrote:
> >
> > You might argue:
> >
> > oktodel: If deleting a pointer to const is illegal because it alters a
> > const then constructing a const should be illegal also!
> >
> > notoktodel: Yes, but, without an object constructed, this whole
> > discussion is moot. There is nothing there to check against const.
> >
> > oktodel: Aaaaah. Well, with the destructor, the object is already
> > deleted before the const check is applied so therefore there is
> > nothing there to check against const.
>
> You have to accept that both points of view are reasonable; you
> explained very well that point of view (if an object ceases to
> exist, then it was not modified, it simply doesn't exist anymore,
> so talking about the object having a different contents doesn't
> make sense).
>
> On the other hand, the thing is that if you have p defined as
>
> const T * p;
>
> That means that *p may not be modified. Now, before `delete p',
> *p is X (some specific value). After executing `delete p', *p
> is nothing (well, it is indeterminate, but we could reasonably
> accept that it is "nothing").
>
> So, since X is not equal to "nothing", then the effect of the
> statement `delete p' did modify *p, didn't it?
>

As much as:

const char* p = new char[40];

modifies it.

I am not a hard ass about this kind of thing. It's just interesting
discussion.

Walt Howard

James Dennett

unread,
Nov 19, 2000, 3:00:00 AM11/19/00
to

It might be (a) safer, because it can catch problems such as this, and (b)
faster, if, e.g., address registers are larger than arithmetic registers.



> > I've never worked on such a system, nor do I know of the existence of
> > such
> > a beast, but I can imagine that it might be useful in tracking down
> > errors
> > in code which did sloppy manipulation of raw pointers.
> IMHO just a copying of any pointers should _never_ crash a program.

I've been directed to clause 3.7.3.2, paragraph 4 of the C++ standard, which
states

If the argument given to a deallocation function in the standard
library [which includes ::operator delete --ark] is a pointer that
is not the null pointer value, the deallocation function shall
deallocate the storage referenced by the pointer, rendering invalid
all pointers referring to any part of the deallocated storage.
The effect of using an invalid pointer value (including passing
it to a deallocation function) is undefined.

[Footnote: On some implementations, it causes a system-generated
runtime fault]

If you accept that copying a pointer is a "use" of that pointer'v value,
then this gives the implementation license to do whatever it wishes if
you copy a pointer which has just been passed to delete.

In all the C++ code I've read or written I've never seen any reason to
read the value of a pointer which has just been deleted.

In order to avoid recycling an old discussion, anyone who is interested
might search for previous discussions as to whether it's possible to tell
if a deleted pointer has been changed by the implementation. I believe
that the conclusion was that it is possible to tell if the bit pattern
has changed by using memcpy/memcmp, but that there is no portable way to
tell if the pointer's value has changed as the only way to test would be
to ask the implementation to compare its current value to an old value,
and that would constitute use of an invalid pointer, and hence undefined
behaviour.

-- James Dennett <jden...@acm.org>

Balog Pal

unread,
Nov 19, 2000, 3:00:00 AM11/19/00
to

"Carlos Moreno" <mor...@cyberx.com> wrote

> Phew!!! I thought I was completely alone on this!! But I'm glad to
> see that at least one experienced programmer shares (100%, I would
> say) my point of view...

There are surely lots of others too.

> ure, forbidding the deletion would either
> force you to use const_cast always when you (the owner of the allocated
> object) delete, or to drop constness for dynamically allocated
> objects...

I see no problem with forcing a const-cast. Anyone can point a situation
where deleting through const pointers is really good and needed, and also
something comes up requently? If figures could show most instances of the
situation is indeed a bug, the feature that allows it to slip by is
something bad.

Paul

Carlos Moreno

unread,
Nov 19, 2000, 3:00:00 AM11/19/00
to

Walt Howard wrote:
>
> > On the other hand, the thing is that if you have p defined as
> >
> > const T * p;
> >
> > That means that *p may not be modified. Now, before `delete p',
> > *p is X (some specific value). After executing `delete p', *p
> > is nothing (well, it is indeterminate, but we could reasonably
> > accept that it is "nothing").
> >
> > So, since X is not equal to "nothing", then the effect of the
> > statement `delete p' did modify *p, didn't it?
> >
>
> As much as:
>
> const char* p = new char[40];
>
> modifies it.

Of course. But the (IMO important) difference is that in this case,
you can't compare *p before and after that statement, because
before the statement, *the pointer* itself didn't exist!!! That
alleged "modification" is absolutely harmless; there is no point
in wanting to prevent client code (or simply, code) from performing
that action.

When you delete, the object ceases to exist, but the pointer
doesn't!! So, talking about accidental deletion makes sense
(even though, as many have argued, might be a symptom of plain
stupidity -- I insist that not necessarily), and accidental
deletion might be very harmful, because the pointer keeps
being there to dereference it. In the case of creation
and initialization, the pointer was not even there before...
And there is no harm in doing that.

> I am not a hard ass about this kind of thing. It's just interesting
> discussion.

Of course it is! As James said, and I agree, both points of
view do have a solid logic in their favour. I normally tend
to favor the one that prevents mistakes (that the mistakes
are due to stupidity or not). In this case, I must agree that
there is another argument in favor of the way that it is
defined by the standard: having to use const_cast whenever
you (legitimately) have to delete a pointer to const would
be a hassle -- and having to drop the constness of an object
only because you're dynamically allocating it, that would be
plain stupidity! :-)

Cheers,

Carlos
--

James Dennett

unread,
Nov 19, 2000, 3:00:00 AM11/19/00
to
Mark Williams wrote:
>
> In article <J0+Xh4Aq...@ntlworld.com>,
> Francis Glassborow <fran...@robinton.demon.co.uk> wrote:
> > In article <3A155458...@cyberx.com>, Carlos Moreno
> > <mor...@cyberx.com> writes
> > >So, this tells me that surely, delete does not change the value of
> > >the pointer (as we should all expect -- of course, since delete is an
> > >operator, and not a function that receives the pointer by value, your
> > >remark is reasonable).
> >
> > But the Standard explicitly says otherwise. The value of p after
> > delete p is indeterminate.
>
> Not true. The value of p cannot be used as a pointer. The value of p
> *can* be copied to an array of char.
>
> char tmp1[sizeof(p)], tmp2[sizeof(p)];
> memcpy(&p, tmp1, sizeof(p));
> delete p;
> memcpy(&p, tmp2, sizeof(p));
> assert(memcmp(tmp1, tmp2, sizeof(p)));

I don't think you'll find anything in the C++ Standard which says that
the bit pattern of p can't be changed by the implementation when you
call "delete p", even if its _value_ is unchanged.

AFAIK, your assertion might be invalid.

-- James Dennett <jden...@acm.org>

Carlos Moreno

unread,
Nov 19, 2000, 3:00:00 AM11/19/00
to

> [...]

> If you accept that copying a pointer is a "use" of that pointer'v value,
> then this gives the implementation license to do whatever it wishes if
> you copy a pointer which has just been passed to delete.
>
> In all the C++ code I've read or written I've never seen any reason to
> read the value of a pointer which has just been deleted.

I have a related question... How come this code works?

int values[10] = { .... };

find (values, values + 10, some_value);


I mean, values+10 is an invalid pointer -- it could be pointing to
memory that is marked by hardware as read-only, or even invalid...
However, that snippet of code is guaranteed to work...

Doing something like find (&values[0], &values[10], val) is
what leads to undefined behaviour (even if 99.999% of the compilers
would accept it in most cases), but reading the value of the pointer
(values + 10) inside the function, to compare it against the temp
iterator (pointer), is definitely valid...

So, how do we concile this with the initial Andrew's (whoever that
guy may be :-)) comment, and subsequent explanations?? (I don't
think both situations are unrelated...)

Carlos
--

Dietmar Kuehl

unread,
Nov 19, 2000, 3:00:00 AM11/19/00
to
Hi,
Carlos Moreno (mor...@cyberx.com) wrote:
: I have a related question... How come this code works?

: int values[10] = { .... };
: find (values, values + 10, some_value);

The standard requires that you can form the address 'values + 10'. That's
why this works. How the implementation achieves it to make this legal is
up to the implementation. An obvious (but by no means required) approach
is to allocate more elements than requested (and leaving additional
elements uninitialized, of course).
--
<mailto:dietma...@yahoo.de> <http://www.dietmar-kuehl.de/~kuehl/>
I am a realistic optimist - that's why I appear to be slightly pessimistic

James Kanze

unread,
Nov 20, 2000, 3:00:00 AM11/20/00
to
James Dennett wrote:

> I don't think you'll find anything in the C++ Standard which says that
> the bit pattern of p can't be changed by the implementation when you
> call "delete p", even if its _value_ is unchanged.

I don't think you'll find anything in either the C or the C++ standard


which says that the bit pattern of p can't be changed by the

implementation, even without a call to delete.

This could even be reasonable in some cases. Older Intel processors
used a segment:offset addressing where many bit patters could point to
the same memory. When comparing pointers, one solution would be to
normalize them to one specific representation. I could easily imagine
a compiler then writing the normalized form back, to avoid the need to
normalize again later.

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627

James Kanze

unread,
Nov 20, 2000, 3:00:00 AM11/20/00
to
Mark Williams wrote:

> In article <J0+Xh4Aq...@ntlworld.com>,
> Francis Glassborow <fran...@robinton.demon.co.uk> wrote:
> > In article <3A155458...@cyberx.com>, Carlos Moreno
> > <mor...@cyberx.com> writes
> > >So, this tells me that surely, delete does not change the value of
> > >the pointer (as we should all expect -- of course, since delete is an
> > >operator, and not a function that receives the pointer by value, your
> > >remark is reasonable).

> > But the Standard explicitly says otherwise. The value of p after
> > delete p is indeterminate.

> Not true. The value of p cannot be used as a pointer. The value of p
> *can* be copied to an array of char.

Anything can be copied to an array of char, even uninitialized memory.

> char tmp1[sizeof(p)], tmp2[sizeof(p)];
> memcpy(&p, tmp1, sizeof(p));
> delete p;
> memcpy(&p, tmp2, sizeof(p));
> assert(memcmp(tmp1, tmp2, sizeof(p)));

The assert is not guaranteed to succeed. Even without the delete, the
assert is not guaranteed to succeed.

James Kanze

unread,
Nov 20, 2000, 3:00:00 AM11/20/00
to
"Sergey P. Derevyago" wrote:

> Andrew Koenig wrote:
> > Carlos> In C, with free(p), the answer to your question used to be trivial
> >:-)

> > Really? In C, after free(p), you cannot be assured even of being

> > able to copy the value of p without your program crashing. The


> > same is true of C++.

> Hmm. Did you say that the following snippet of code may crash my
> program?

> int r=rand();
> void* p=reinterpret_cast<void*>(r);
> cout<<p;

He did.

> How?

Because the standard says it is undefined behavior. On at least some
implementations of early 80286 compilers, in protected mode, for
example, the compiler would push the arguments onto the stack by using
an LES instruction to load them into the registers, then pushing the
registers. And loading an invalide segment into ES would cause the
processor to generate a hardware interruption.

A more likely problem today, after delete or free, is that the
compiler will mark the variable as unused in its live analysis. This
could easily result in the variable having an apparently random value,
or even changing at random times later.

James Kanze

unread,
Nov 20, 2000, 3:00:00 AM11/20/00
to
Carlos Moreno wrote:

> Andrew Koenig wrote:

> > Carlos> In C, with free(p), the answer to your question used to be trivial
> >:-)

> > Really? In C, after free(p), you cannot be assured even of being
> > able to copy the value of p without your program crashing.

> ??? You totally got me on this one... I have absolutely no clue of


> what you're referring to. Still, I trust you, of course :-)

> What I'm having trouble to understand is the following: free is a
> function, that receives its parameter by value. So, how could that
> function do anything to *the value* of that parameter??

The same way that calling the operator delete function can affect the
value of its parameter. Both function are part of the language. The
compiler "knows" their exact semantics (even more so in the case of
free, since the user is not allowed to replace it). In both cases,
*any* access to the pointer, except via memcpy, after the call to the
function is undefined behavior. Thus, the compiler, knowing that
there is no way for a conforming program to tell the difference, can
legally do what ever it wants with the pointer.

Note that most optimizers do live analysis, to determine which
variables are live, and which aren't. After a call to operator delete
or to free, the pointer is no longer live.

> Of course, the pointer, after calling free, is non-dereferenceable,
> but that has nothing to do with *the value* of p, which I don't see
> how could not remain unchanged, or how using it (as in using its
> value *without dereferencing it*) could be any trouble.

Accessing the pointer after free or operator delete invokes undefined
behavior, according to the standard. There is some question, perhaps,
concerning accessing it via memcpy. On the other hand, I don't see
how a conforming program could tell whether it had been modified, even
using memcpy, since the standard says nothing about the bit pattern of
the pointer.

Brian McNamara!

unread,
Nov 20, 2000, 3:00:00 AM11/20/00
to
Carlos Moreno <mor...@cyberx.com> once said:
>I have a related question... How come this code works?
>
> int values[10] = { .... };
> find (values, values + 10, some_value);
>
>I mean, values+10 is an invalid pointer -- it could be pointing to
>memory that is marked by hardware as read-only, or even invalid...
>However, that snippet of code is guaranteed to work...
...
>So, how do we concile this with the initial Andrew's (whoever that
>guy may be :-)) comment, and subsequent explanations?? (I don't
>think both situations are unrelated...)

I think the answer is simply because "that's what the standard says".
Specifically, in the example above, value+10 is not an invalid pointer,
due to special exception for one-past-the-end of arrays (e.g. 5.7p5:

...Moreover, if the expression P points to the last element of an array
object, the expression (P)+1 points one past the last element of the
array object, and if the expression Q points one past the last element
of an array object, the expression (Q)-1 points to the last element of
the array object. If both the pointer operand and the result point to
elements of the same array object, or one past the last ele-ment of the
array object, the evaluation shall not produce an overflow; otherwise,
the behavior is undefined.

). Note that, on the other hand, the standard explicitly says that the
value of a pointer that is deleted is indeterminate.

It seems to me that both "rules" make sense for most programs; there is
typically no good reason to be interested in a pointers value after its
object is deleted, but there are lots of good reasons to want to talk
about the pointer one-past-the-end of an array (namely std::find,
std::copy, std::transform, ...).

--
Brian McNamara

Andrew Koenig

unread,
Nov 20, 2000, 3:00:00 AM11/20/00
to
James> In all the C++ code I've read or written I've never seen any
James> reason to read the value of a pointer which has just been
James> deleted.

Just to inject a bit of ancient history into the discussion:

Once upon a time (ca. 1977), the definition of malloc and free in the
C library were such that free was guaranteed not to change the memory
freed. In other words, the memory was guaranteed to remain untouched
until at least the next call to malloc.

This guarantee allowed constructs such as the following:

while (p) {
free(p);
p = p->next;
}

Indeed, times have changed.


--
Andrew Koenig, a...@research.att.com, http://www.research.att.com/info/ark

Gabriel Dos_Reis

unread,
Nov 20, 2000, 3:00:00 AM11/20/00
to
"Sergey P. Derevyago" <non-ex...@iobox.com> writes:

[...]

| And if delete is allowed to change the pointer why it doesn't set the
| pointer
| to 0? IMHO it'll be quite reasonable.

Why 0 and not 0xffffffffffff nor 0xdeadbeef?

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Andrew Koenig

unread,
Nov 20, 2000, 3:00:00 AM11/20/00
to
Carlos> I have a related question... How come this code works?

Carlos> int values[10] = { .... };

Carlos> find (values, values + 10, some_value);

Carlos> I mean, values+10 is an invalid pointer -- it could be
Carlos> pointing to memory that is marked by hardware as read-only, or
Carlos> even invalid... However, that snippet of code is guaranteed
Carlos> to work...

values + 10 is a valid pointer. It's just not dereferenceable.
Implementations are required to allow the formation of a pointer
to one past the last element of any array or one past any object.

Mark Williams

unread,
Nov 20, 2000, 3:00:00 AM11/20/00
to
In article <3A190366...@dresdner-bank.de>,

James Kanze <James...@dresdner-bank.de> wrote:
> Mark Williams wrote:
>
> > In article <J0+Xh4Aq...@ntlworld.com>,
> > Francis Glassborow <fran...@robinton.demon.co.uk> wrote:
> > > In article <3A155458...@cyberx.com>, Carlos Moreno
> > > <mor...@cyberx.com> writes
> > > >So, this tells me that surely, delete does not change the value
of
> > > >the pointer (as we should all expect -- of course, since delete
is an
> > > >operator, and not a function that receives the pointer by value,
your
> > > >remark is reasonable).
>
> > > But the Standard explicitly says otherwise. The value of p after
> > > delete p is indeterminate.
>
> > Not true. The value of p cannot be used as a pointer. The value of p
> > *can* be copied to an array of char.
>
> Anything can be copied to an array of char, even uninitialized memory.
>
> > char tmp1[sizeof(p)], tmp2[sizeof(p)];
> > memcpy(&p, tmp1, sizeof(p));
> > delete p;
> > memcpy(&p, tmp2, sizeof(p));
> > assert(memcmp(tmp1, tmp2, sizeof(p)));
>
> The assert is not guaranteed to succeed.

Non volatile objects retain their last stored value. The bytes of p may
be accessed through an lvalue of unsigned character type (amongst other
things). lvalues refer to objects (by definition), so the bytes of p are
objects. (quick summary of an argument that occured on comp.std.c some
time ago)

So the bytes making up p cannot change without an explicit store (either
to the bytes themselves, to p, or to an object containing p).

> Even without the delete, the
> assert is not guaranteed to succeed.

I assume you are saying that there could be multiple, equivalent
representations for p, and that the compiler may choose to switch
representations periodically. If the following program is conforming,
then I dont believe that is the case:

void *p = malloc(100);
unsigned char tmp[sizeof(p)];
unsigned char *q = &p;
for (int i = 0; i < sizeof(p); i++) {
tmp[i] = q[i];
do_something_that_doesnt_modify_p();
}

for (int i = 0; i < sizeof(p); i++) {
q[i] = tmp[i];
}

p[5] = 0;
free(p);

I believe the standard allows me to copy the bytes of an object into an
unsigned char array, and back again, without modifying its value. But if
p flips between two or more representations, tmp could end up with a
"mix", and the final copy back would create a garbage pointer.

-------------
Mark Williams


Sent via Deja.com http://www.deja.com/
Before you buy.

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Sergey P. Derevyago

unread,
Nov 20, 2000, 3:00:00 AM11/20/00
to
Andrew Koenig wrote:
> Once upon a time (ca. 1977), the definition of malloc and free in the
> C library were such that free was guaranteed not to change the memory
> freed. In other words, the memory was guaranteed to remain untouched
> until at least the next call to malloc.
>
> This guarantee allowed constructs such as the following:
>
> while (p) {
> free(p);
> p = p->next;
> }
>
> Indeed, times have changed.
Surely, but

void* sv=ptr;
free(ptr);
assert(ptr==sv);

is still legal, isn't it?

And if

int r=rand();
void* p=reinterpret_cast<void*>(r);
cout<<p;

is not guaranteed to work than some C definitions like

#define SIG_IGN ((void (*)(int))1) /* Ignore action */
#define SIG_ERR ((void (*)(int))-1) /* Error return */

in <signal.h> becomes illegal?!

So my question is: Am I allowed to pass/copy and compare (but not to
dereference) random generated pointers?


--
With all respect, Sergey. http://cpp3.virtualave.net/
mailto : ders at skeptik.net

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Ross Smith

unread,
Nov 21, 2000, 12:29:09 AM11/21/00
to
"Sergey P. Derevyago" wrote:
>
> Andrew Koenig wrote:
> > Once upon a time (ca. 1977), the definition of malloc and free in the
> > C library were such that free was guaranteed not to change the memory
> > freed. In other words, the memory was guaranteed to remain untouched
> > until at least the next call to malloc.
> >
> > This guarantee allowed constructs such as the following:
> >
> > while (p) {
> > free(p);
> > p = p->next;
> > }
> >
> > Indeed, times have changed.
> Surely, but
>
> void* sv=ptr;
> free(ptr);
> assert(ptr==sv);
>
> is still legal, isn't it?

No (if by "legal" you mean "portable").

The usual example of a situation where this sort of thing would fail is
on hardware with separate address and data registers, with the address
registers checked whenever they're used to ensure they point to a piece
of memory the program is allowed to access. If free(ptr) marks the
pointed-to block as no longer wanted, reading ptr in the assert will
trigger an illegal-access error.

> And if
>
> int r=rand();
> void* p=reinterpret_cast<void*>(r);
> cout<<p;
>
> is not guaranteed to work than some C definitions like
>
> #define SIG_IGN ((void (*)(int))1) /* Ignore action */
> #define SIG_ERR ((void (*)(int))-1) /* Error return */
>
> in <signal.h> becomes illegal?!

If it was intended to be _portable_ code, then yes, it's definitely
illegal. But I don't believe any such code can be found in any of the
relevant standards (C89, C99, C++, Posix, SUS). This is just the
definition used in that header on one particular system, and it's
perfectly all right (and frequently absolutely necessary) for an
_implementation_ of the standard library to use code that's non-portable
but known to work on that particular system.

> So my question is: Am I allowed to pass/copy and compare (but not to
> dereference) random generated pointers?

In portable code? Absolutely not. In code that only needs to work on
some known subset of all the systems out there? Depends on the systems.

--
Ross Smith <ros...@ihug.co.nz> The Internet Group, Auckland, New Zealand
========================================================================
"There are many technical details that make Linux attractive to the
sort of people to whom technical details are attractive." -- Suck

Carlos Moreno

unread,
Nov 21, 2000, 3:00:00 AM11/21/00
to

"Brian McNamara!" wrote:
>
> I think the answer is simply because "that's what the standard says".

Fair enough! :-)

> It seems to me that both "rules" make sense for most programs; there is
> typically no good reason to be interested in a pointers value after its
> object is deleted

Of course! It was clear to me that disallowing the use of a
pointer after delete is reasonable -- my question was rather
oriented to the "language lawyering" side; I was having
difficulty in understanding and putting together two *apparently*
contradictory features that both seem reasonable.

Thanks for your reply. And thanks Dietmar and Andrew for their
replies!

Cheers,

Carlos
--

Francis Glassborow

unread,
Nov 21, 2000, 3:00:00 AM11/21/00
to
In article <3A188D60...@cyberx.com>, Carlos Moreno
<mor...@cyberx.com> writes
>I mean, values+10 is an invalid pointer -- it could be pointing to
>memory that is marked by hardware as read-only, or even invalid...
>However, that snippet of code is guaranteed to work...

But it isn't, it is a specific requirement that the address of one
beyond the end of an array is a valid address though it must not be
dereferenced. This rule is exactly designed to cater for memory checked
systems.


Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

Francis Glassborow

unread,
Nov 21, 2000, 3:00:00 AM11/21/00
to
In article <8v9kji$1ji$1...@nnrp1.deja.com>, Mark Williams <markw65@my-
deja.com> writes

>Not true. The value of p cannot be used as a pointer. The value of p
>*can* be copied to an array of char.
>
>char tmp1[sizeof(p)], tmp2[sizeof(p)];
>memcpy(&p, tmp1, sizeof(p));
>delete p;
>memcpy(&p, tmp2, sizeof(p));
>assert(memcmp(tmp1, tmp2, sizeof(p)));

I am not convinced that the standard requires that the asserted
expression evaluate to true.

Erik Max Francis

unread,
Nov 21, 2000, 3:00:00 AM11/21/00
to
"Sergey P. Derevyago" wrote:

> And if
>
> int r=rand();
> void* p=reinterpret_cast<void*>(r);
> cout<<p;
>
> is not guaranteed to work than some C definitions like
>
> #define SIG_IGN ((void (*)(int))1) /* Ignore action */
> #define SIG_ERR ((void (*)(int))-1) /* Error return */
>
> in <signal.h> becomes illegal?!

The actual implementation of SIG_IGN and SIG_ERR are dependent on the
implemention. On _your_ implementation they are defined this way
because the library writers know for a fact that it will work. That
doesn't make it Standard conforming code.

--
Erik Max Francis / m...@alcyone.com / http://www.alcyone.com/max/
__ San Jose, CA, US / 37 20 N 121 53 W / ICQ16063900 / &tSftDotIotE
/ \ A physicist is an atom's way of knowing about atoms.
\__/ George Wald
Maths reference / http://www.alcyone.com/max/reference/maths/
A mathematics reference.

James Kanze

unread,
Nov 21, 2000, 3:00:00 AM11/21/00
to
Mark Williams wrote:

> > Anything can be copied to an array of char, even uninitialized memory.

> > > char tmp1[sizeof(p)], tmp2[sizeof(p)];
> > > memcpy(&p, tmp1, sizeof(p));
> > > delete p;
> > > memcpy(&p, tmp2, sizeof(p));
> > > assert(memcmp(tmp1, tmp2, sizeof(p)));

> > The assert is not guaranteed to succeed.

> Non volatile objects retain their last stored value.

value != bit pattern.

> The bytes of p
> may be accessed through an lvalue of unsigned character type
> (amongst other things). lvalues refer to objects (by definition), so
> the bytes of p are objects. (quick summary of an argument that
> occured on comp.std.c some time ago)

> So the bytes making up p cannot change without an explicit store
> (either to the bytes themselves, to p, or to an object containing
> p).

I rather suspect that they cannot change without the user doing
something. I'm pretty sure (but not 100%), however, that a legal
implementation could change bit patterns during a read.

> > Even without the delete, the
> > assert is not guaranteed to succeed.

> I assume you are saying that there could be multiple, equivalent
> representations for p, and that the compiler may choose to switch
> representations periodically. If the following program is
> conforming, then I dont believe that is the case:

> void *p = malloc(100);
> unsigned char tmp[sizeof(p)];
> unsigned char *q = &p;
> for (int i = 0; i < sizeof(p); i++) {
> tmp[i] = q[i];
> do_something_that_doesnt_modify_p();
> }
>
> for (int i = 0; i < sizeof(p); i++) {
> q[i] = tmp[i];
> }

> p[5] = 0;
> free(p);

> I believe the standard allows me to copy the bytes of an object into
> an unsigned char array, and back again, without modifying its
> value. But if p flips between two or more representations, tmp could
> end up with a "mix", and the final copy back would create a garbage
> pointer.

I don't know whether the above program would be considered
conforming; it's a good question. The standard does allow copying to
an unsigned char array, and back again, but it says nothing about
doing other things during the copy. I would argue that this isn't a
copy, because it isn't "atomic", even within the thread.

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627

Dylan Nicholson

unread,
Nov 21, 2000, 3:00:00 AM11/21/00
to
In article <3A188B25...@cyberx.com>,
Carlos Moreno <mor...@cyberx.com> wrote:
>
<snip>

> Of course it is! As James said, and I agree, both points of
> view do have a solid logic in their favour. I normally tend
> to favor the one that prevents mistakes (that the mistakes
> are due to stupidity or not). In this case, I must agree that
> there is another argument in favor of the way that it is
> defined by the standard: having to use const_cast whenever
> you (legitimately) have to delete a pointer to const would
> be a hassle -- and having to drop the constness of an object
> only because you're dynamically allocating it, that would be
> plain stupidity! :-)
>

Why would it be a hassle? Certainly free() only accepts a non-const
pointer. I for one can't see why delete should have different
semantics to free, and would never use delete on a const pointer. As
far as I'm concerned I should be able to pass a const pointer into a
function and be absolutely sure the pointer and its associated object
is still valid after it returns. Likewise I want to be able to return
const pointers from functions, knowing that the data pointed to will
remain valid. If constness didn't guarantee me this, I'd want
something that did.
Furthermore VC++ is hardly the only compiler to consider this an error -
both the Sun and AIX (xlC_r) compilers do the same. I would be
intrigued to see a convincing explanation of why the standard allows
such a thing.

Dylan


Sent via Deja.com http://www.deja.com/
Before you buy.

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Andrew Koenig

unread,
Nov 21, 2000, 3:00:00 AM11/21/00
to
ark> Indeed, times have changed.

Sergey> Surely, but

Sergey> void* sv=ptr;
Sergey> free(ptr);
Sergey> assert(ptr==sv);

Sergey> is still legal, isn't it?

Absolutely not. The mere act of attempting to fetch the value of
ptr after calling free(ptr) entitles the implementation to do anything
it wants, including crash the program.

Sergey> And if

Sergey> int r=rand();
Sergey> void* p=reinterpret_cast<void*>(r);
Sergey> cout<<p;

Sergey> is not guaranteed to work than some C definitions like

Sergey> #define SIG_IGN ((void (*)(int))1) /* Ignore action */
Sergey> #define SIG_ERR ((void (*)(int))-1) /* Error return */

Sergey> in <signal.h> becomes illegal?!

The standard does not guarantee its meaning, so its behavior
depends on the implementation.

Sergey P. Derevyago

unread,
Nov 21, 2000, 3:00:00 AM11/21/00
to
Francis Glassborow wrote:
> >char tmp1[sizeof(p)], tmp2[sizeof(p)];
> >memcpy(&p, tmp1, sizeof(p));
> >delete p;
> >memcpy(&p, tmp2, sizeof(p));
> >assert(memcmp(tmp1, tmp2, sizeof(p)));
>
> I am not convinced that the standard requires that the asserted
> expression evaluate to true.
>
And what about:

1.
void* p2=p;
delete p;
assert(p==p2);

2.
void* p2=p;
free(p);
assert(p==p2);

3.


char tmp1[sizeof(p)], tmp2[sizeof(p)];
memcpy(&p, tmp1, sizeof(p));
delete p;
memcpy(&p, tmp2, sizeof(p));

assert(memcmp(tmp1, tmp2, sizeof(p))==0);

4.


char tmp1[sizeof(p)], tmp2[sizeof(p)];
memcpy(&p, tmp1, sizeof(p));

free(p);
memcpy(&p, tmp2, sizeof(p));
assert(memcmp(tmp1, tmp2, sizeof(p))==0);

5.
union ptrRep {
void* ptr;
char rep[sizeof(void*)];
} un1, un2;
un1.ptr=un2.ptr=p;
delete un1.ptr;
assert(memcmp(un1.rep, un2.rep, sizeof(ptrRep))==0);

6.
union ptrRep {
void* ptr;
char rep[sizeof(void*)];
} un1, un2;
un1.ptr=un2.ptr=p;
free(un1.ptr);
assert(memcmp(un1.rep, un2.rep, sizeof(ptrRep))==0);

What the standard guarantiees? And why?


--
With all respect, Sergey. http://cpp3.virtualave.net/
mailto : ders at skeptik.net

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Sergey P. Derevyago

unread,
Nov 21, 2000, 3:00:00 AM11/21/00
to
Ross Smith wrote:
> > void* sv=ptr;
> > free(ptr);
> > assert(ptr==sv);

> >
> The usual example of a situation where this sort of thing would fail is
> on hardware with separate address and data registers, with the address
> registers checked whenever they're used to ensure they point to a piece
> of memory the program is allowed to access. If free(ptr) marks the
> pointed-to block as no longer wanted, reading ptr in the assert will
> trigger an illegal-access error.
Do you mean "reading ptr into a special address register"? I'm not sure
that a
comparison like (ptr==sv) can be done in such registers. So the question is
still open.

--
With all respect, Sergey. http://cpp3.virtualave.net/
mailto : ders at skeptik.net

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Balog Pal (mh)

unread,
Nov 21, 2000, 3:00:00 AM11/21/00
to
Gabriel Dos_Reis wrote in message ...

>| And if delete is allowed to change the pointer why it doesn't set the
>| pointer
>| to 0? IMHO it'll be quite reasonable.
>
>Why 0 and not 0xffffffffffff nor 0xdeadbeef?


Because accessing a pointer with walues above is undefined behavior, while
accessing a null pointer is good.

Paul

Mark Williams

unread,
Nov 21, 2000, 3:00:00 AM11/21/00
to
In article <3A1A42E8...@dresdner-bank.de>,

James Kanze <James...@dresdner-bank.de> wrote:
> Mark Williams wrote:
>
> > > Anything can be copied to an array of char, even uninitialized
memory.
>
> > > > char tmp1[sizeof(p)], tmp2[sizeof(p)];
> > > > memcpy(&p, tmp1, sizeof(p));
> > > > delete p;
> > > > memcpy(&p, tmp2, sizeof(p));
> > > > assert(memcmp(tmp1, tmp2, sizeof(p)));
>
> > > The assert is not guaranteed to succeed.
>
> > Non volatile objects retain their last stored value.
>
> value != bit pattern.

Except in the case of unsigned char, which is the only claim I make.

>
> > The bytes of p
> > may be accessed through an lvalue of unsigned character type
> > (amongst other things). lvalues refer to objects (by definition), so
> > the bytes of p are objects. (quick summary of an argument that
> > occured on comp.std.c some time ago)
>
> > So the bytes making up p cannot change without an explicit store
> > (either to the bytes themselves, to p, or to an object containing
> > p).
>
> I rather suspect that they cannot change without the user doing
> something. I'm pretty sure (but not 100%), however, that a legal
> implementation could change bit patterns during a read.

But you presumably accept that it cannot change the *value* of an
unsigned char during a read, and hence it cannot change its bit-pattern.
Hence it cannot change the bit-pattern of anything that contains that
unsigned char.

Of course, by the as-if rule, if the compiler can detect that the bytes
making up the pointer have not been recorded, it can change the
value-representation of the pointer any time it wants to.

I see no wording that the copy must be atomic. And how would you do that
anyway?

You would presumably disallow:

for (i = 0; i < sizeof(p); i++)
q[i] = p[i];

On the grounds that it increments i, compares it against sizeof(p). It
is doing work that is not actually copying the values...

So how about:

switch (sizeof(p)) {
case 1: q[0] = p[0]; break;
case 2: q[0] = p[0]; q[1] = p[1]; break;
case 3: q[0] = ...
...
}

hmmm... if thats the only way to do a copy, we are in trouble :-)

-------------
Mark Williams


Sent via Deja.com http://www.deja.com/
Before you buy.

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Francis Glassborow

unread,
Nov 21, 2000, 3:00:00 AM11/21/00
to
In article <8vcbp3$7lh$1...@nnrp1.deja.com>, Dylan Nicholson <dnich@my-
deja.com> writes

>Why would it be a hassle? Certainly free() only accepts a non-const
>pointer.

But malloc() does not create objects. You need to distinguish between
the delete expression and operator delete (which might well not accept a
const pointer.

> I for one can't see why delete should have different
>semantics to free, and would never use delete on a const pointer.

Fine, and I never delete pointers that I am either not responsible for,
unless the documentation explicitly tells me to (and there is no option
but to provide this in documentation)

> As
>far as I'm concerned I should be able to pass a const pointer into a
>function and be absolutely sure the pointer and its associated object
>is still valid after it returns.

Well you want something the language cannot provide, as a wilful
programmer can simply cast away the const protection. I want something
stronger, I want to be able to pass pointers into functions with the
expectation that they will still be valid on return from the function
unless there is some explicit clue that the object pointed to may go
away (like naming the function 'remove')

> Likewise I want to be able to return
>const pointers from functions, knowing that the data pointed to will
>remain valid.

Same answer, only even stronger, how will you return a pointer from a
function for a mutable object that must not be deleted?

>If constness didn't guarantee me this, I'd want
>something that did.

Fine, but you will also need a way to return a pointer to a mutable
object that must not be destroyed.

>Furthermore VC++ is hardly the only compiler to consider this an error -
> both the Sun and AIX (xlC_r) compilers do the same. I would be
>intrigued to see a convincing explanation of why the standard allows
>such a thing.

Yes, but we changed the rules several years ago and that change was not
just arbitrary. It was making a promise that was vacuous and implying
something that was unsafe: that non-const pointers implied that it was
OK to delete.


Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Carlos Moreno

unread,
Nov 21, 2000, 3:00:00 AM11/21/00
to
Dylan Nicholson wrote:
>
> Furthermore VC++ is hardly the only compiler to consider this an error -
> both the Sun and AIX (xlC_r) compilers do the same.

Hmm, seems like you missed one previous post in this thread. Someone
(sorry, don;t remember the name) mentioned that the reason for VC++
(and other compilers, as you mentioned) to do this, is that in the
pre-standard days that was a rule -- applying delete to a pointer to
const was disallowed (the ARM specifies it that way).

> I would be
> intrigued to see a convincing explanation of why the standard allows
> such a thing.

In that same post, the author explained that the main reasons were
the fact that writing template code is made easier.

As you can see, from other people's points of view, writing templates
is not the only reason; not everyone sees deletion of a pointer as
an action that modifies the object (I do! I agree with your point of
view, as you probablyhave noticed following this thread :-))

Cheers,

Carlos
--

James Dennett

unread,
Nov 21, 2000, 3:00:00 AM11/21/00
to
"Sergey P. Derevyago" wrote:
>
> Ross Smith wrote:
> > > void* sv=ptr;
> > > free(ptr);
> > > assert(ptr==sv);
> > >
> > The usual example of a situation where this sort of thing would fail is
> > on hardware with separate address and data registers, with the address
> > registers checked whenever they're used to ensure they point to a piece
> > of memory the program is allowed to access. If free(ptr) marks the
> > pointed-to block as no longer wanted, reading ptr in the assert will
> > trigger an illegal-access error.
> Do you mean "reading ptr into a special address register"? I'm
not sure
> that a
> comparison like (ptr==sv) can be done in such registers. So the question
is
> still open.

It would also fail on an implementation which favoured rigorous checking,
and inserted its own checks on pointer accesses to test that the programmer
hasn't relied on behaviour which is classified by the Standard as being
undefined.

Not an open question. You can't read the pointer because the Standard says
you can't, at least not in portable code. You implementation may define
the
undefined behaviour to do what you expect, but I wouldn't count on it.

-- James Dennett <jden...@acm.org>

Francis Glassborow

unread,
Nov 21, 2000, 3:00:00 AM11/21/00
to
In article <3A1A6219...@iobox.com>, Sergey P. Derevyago <non-
exis...@iobox.com> writes

>What the standard guarantiees? And why?
None for any of the cases where you compare addresses directly, and only
that you may get an assert failure where you compare the raw memory.


Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Gabriel Dos_Reis

unread,
Nov 21, 2000, 3:00:00 AM11/21/00
to
"Balog Pal \(mh\)" <pa...@lib.hu> writes:

| Gabriel Dos_Reis wrote in message ...
|
| >| And if delete is allowed to change the pointer why it doesn't set the
| >| pointer
| >| to 0? IMHO it'll be quite reasonable.
| >
| >Why 0 and not 0xffffffffffff nor 0xdeadbeef?
|
|
| Because accessing a pointer with walues above is undefined behavior, while
| accessing a null pointer is good.

Maybe. But now, how could you distinguish between a released pointer
and a pointer explicitly initialized to zero for debugging purposes?

(Yes, I agree the Debugger Oriented Programming paradigm isn't
scalable but there are people out there using it and C++ has better
support it :-)

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Ron Natalie

unread,
Nov 21, 2000, 3:00:00 AM11/21/00
to

"Sergey P. Derevyago" wrote:

> 1.
> void* p2=p;
> delete p;
> assert(p==p2);

Invalid, no guarantees about the usability of p after delete returns.


>
> 2.
> void* p2=p;
> free(p);
> assert(p==p2);

As far as C++ is concerened. Nothing interesting has happened. It doesn't
address the validity of a pointer value passed to a subroutine (which as far
as it is concerned, that's all free is). C doesn't have any words about not
being able to examine the pointer after free, so I suspect your OK.
>
> 3.


> char tmp1[sizeof(p)], tmp2[sizeof(p)];
> memcpy(&p, tmp1, sizeof(p));
> delete p;
> memcpy(&p, tmp2, sizeof(p));

> assert(memcmp(tmp1, tmp2, sizeof(p))==0);

Presumably ok...the value of p is not used here.
>
> 4.


> char tmp1[sizeof(p)], tmp2[sizeof(p)];
> memcpy(&p, tmp1, sizeof(p));

> free(p);
> memcpy(&p, tmp2, sizeof(p));
> assert(memcmp(tmp1, tmp2, sizeof(p))==0);

Same as #3.

>
> 5.
> union ptrRep {
> void* ptr;
> char rep[sizeof(void*)];
> } un1, un2;
> un1.ptr=un2.ptr=p;
> delete un1.ptr;
> assert(memcmp(un1.rep, un2.rep, sizeof(ptrRep))==0);

Undefined behavior, no guarantees about storing into one union
member and reading from another. Boy did we ever get burned on
that one. The BSD UNIX kernel did stuff like this all the time,
however we were working on a machine where the partial word size
was encoded in the low order bits. While a normal pointer cast
emitted code in the C compiler to handle this, conversion via union
left the ptr with an invalid representation.


>
> 6.
> union ptrRep {
> void* ptr;
> char rep[sizeof(void*)];
> } un1, un2;
> un1.ptr=un2.ptr=p;
> free(un1.ptr);
> assert(memcmp(un1.rep, un2.rep, sizeof(ptrRep))==0);

Same as #6

It is loading more messages.
0 new messages