Topic: deleted pointers in a container


Author: kavdeiv@mail.ru (Kiril Avdeiv)
Date: Sun, 27 May 2001 19:05:54 GMT
Raw View
James Dennett <jdennett@acm.org> wrote in message news:<3B0EE5D3.7C7D90B6@acm.org>...
> Kiril Avdeiv wrote:
> >
> > James Dennett <jdennett@acm.org> wrote in message news:<3AF69057.1778277E@acm.org>...
> > > Assaf Lavie wrote:
> > > >
> > > > >IIRC that's not specified by the Standard.  Maybe it should
> > > > >be, or maybe it is and I've just missed it.
> > > >
> > > > Why do you make the assertion that copying deallocated pointers (not
> > > > de-referencing them) yields undefined behavior if it is not specified by the
> > > > standard?
> > >
> > > The fact that copying deallocated pointers yields undefined
> > > behaviour *is* clearly stated by the Standard.
> >
> > James, I am very grateful if you show where it is stated.
>
> 5.3.5/4 contains "Note: the value of a pointer that refers to
> deallocated storage is indeterminate." but I don't think that's
> the piece I want.
>
> Ah...  3.7.3.2/4 is the one: "If the argument given to a
> deallocation function in the standard library is a pointer that
> is not the null pointer value (4.10), the deallocation function
> shall deallocate the store 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 passint it to a deallocation function) is undefined."
>
> There's a footnote (33) which points out that "On some
> implementations, it causes a system-generated runtime fault."
>
> If you agree that copying a pointer is a "use" of the pointer,
> this clearly states that
>
> int *p(new int);
> delete p;  // invalidates p
> int *q(p); // use of invalid pointer
>
> invokes undefined behaviour.

Thank you for the answer.

However, the standard says "an object or a non-overloaded function is
used if it appears in a potentially evaluated expression". Given that,
if we take the cuttings from the standard that you quoted, we have
that there's no way to assign to an unitialized pointer:

int   i,  * pi;
pi = &i;   // pi - an invalid pointer value - is used. Undefined
behavior?


I think the findings are enough for a defect report, because the
sentence "The effect of using an invalid pointer value (including
passint it to a deallocation function) is undefined" is incorrect.


Thank you
Kiril

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: James Dennett <jdennett@acm.org>
Date: Mon, 28 May 2001 13:30:42 GMT
Raw View
Kiril Avdeiv wrote:
>
> James Dennett <jdennett@acm.org> wrote in message news:<3B0EE5D3.7C7D90B6@acm.org>...
> > Kiril Avdeiv wrote:
> > >
> > > James Dennett <jdennett@acm.org> wrote in message news:<3AF69057.1778277E@acm.org>...
> > > > Assaf Lavie wrote:
> > > > >
> > > > > >IIRC that's not specified by the Standard.  Maybe it should
> > > > > >be, or maybe it is and I've just missed it.
> > > > >
> > > > > Why do you make the assertion that copying deallocated pointers (not
> > > > > de-referencing them) yields undefined behavior if it is not specified by the
> > > > > standard?
> > > >
> > > > The fact that copying deallocated pointers yields undefined
> > > > behaviour *is* clearly stated by the Standard.
> > >
> > > James, I am very grateful if you show where it is stated.
> >
> > 5.3.5/4 contains "Note: the value of a pointer that refers to
> > deallocated storage is indeterminate." but I don't think that's
> > the piece I want.
> >
> > Ah...  3.7.3.2/4 is the one: "If the argument given to a
> > deallocation function in the standard library is a pointer that
> > is not the null pointer value (4.10), the deallocation function
> > shall deallocate the store 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 passint it to a deallocation function) is undefined."
> >
> > There's a footnote (33) which points out that "On some
> > implementations, it causes a system-generated runtime fault."
> >
> > If you agree that copying a pointer is a "use" of the pointer,
> > this clearly states that
> >
> > int *p(new int);
> > delete p;  // invalidates p
> > int *q(p); // use of invalid pointer
> >
> > invokes undefined behaviour.
>
> Thank you for the answer.
>
> However, the standard says "an object or a non-overloaded function is
> used if it appears in a potentially evaluated expression". Given that,
> if we take the cuttings from the standard that you quoted, we have
> that there's no way to assign to an unitialized pointer:
>
> int   i,  * pi;
> pi = &i;   // pi - an invalid pointer value - is used. Undefined
> behavior?

I don't think so.  The *value* of pi is not used in the statement
"pi = &i;" although the object pi might be said to be used.  The
statement does not depend in any way on the previous value of pi.

> I think the findings are enough for a defect report, because the
> sentence "The effect of using an invalid pointer value (including
> passint it to a deallocation function) is undefined" is incorrect.

I think that the distinction between using an object and using
the value of that object means that this is not a defect.

-- James Dennett

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "James Kuyper Jr." <kuyper@wizard.net>
Date: Mon, 28 May 2001 22:57:17 GMT
Raw View
Kiril Avdeiv wrote:
...
> However, the standard says "an object or a non-overloaded function is
> used if it appears in a potentially evaluated expression". Given that,
> if we take the cuttings from the standard that you quoted, we have
> that there's no way to assign to an unitialized pointer:
>
> int   i,  * pi;
> pi = &i;   // pi - an invalid pointer value - is used. Undefined

You're confusing the use of a variable with use of the value stored in
that variable. The variable 'pi' is used, but the invalid value that was
stored in pi is NOT used. It is simply being replaced by a new value,
which happens to be a valid one.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: kavdeiv@mail.ru (Kiril Avdeiv)
Date: Mon, 28 May 2001 23:00:54 GMT
Raw View
James Dennett <jdennett@acm.org> wrote in message news:<3B125093.A3D953A1@acm.org>...
> Kiril Avdeiv wrote:
> >
> > James Dennett <jdennett@acm.org> wrote in message news:<3B0EE5D3.7C7D90B6@acm.org>...
> > > Kiril Avdeiv wrote:
> > > >
> > > > James Dennett <jdennett@acm.org> wrote in message news:<3AF69057.1778277E@acm.org>...
> > > > > Assaf Lavie wrote:
> > > > > >
> > > > > > >IIRC that's not specified by the Standard.  Maybe it should
> > > > > > >be, or maybe it is and I've just missed it.
> > > > > >
> > > > > > Why do you make the assertion that copying deallocated pointers (not
> > > > > > de-referencing them) yields undefined behavior if it is not specified by the
> > > > > > standard?
> > > > >
> > > > > The fact that copying deallocated pointers yields undefined
> > > > > behaviour *is* clearly stated by the Standard.
> > > >
> > > > James, I am very grateful if you show where it is stated.
> > >
> > > 5.3.5/4 contains "Note: the value of a pointer that refers to
> > > deallocated storage is indeterminate." but I don't think that's
> > > the piece I want.
> > >
> > > Ah...  3.7.3.2/4 is the one: "If the argument given to a
> > > deallocation function in the standard library is a pointer that
> > > is not the null pointer value (4.10), the deallocation function
> > > shall deallocate the store 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 passint it to a deallocation function) is undefined."
> > >
> > > There's a footnote (33) which points out that "On some
> > > implementations, it causes a system-generated runtime fault."
> > >
> > > If you agree that copying a pointer is a "use" of the pointer,
> > > this clearly states that
> > >
> > > int *p(new int);
> > > delete p;  // invalidates p
> > > int *q(p); // use of invalid pointer
> > >
> > > invokes undefined behaviour.
> >
> > Thank you for the answer.
> >
> > However, the standard says "an object or a non-overloaded function is
> > used if it appears in a potentially evaluated expression". Given that,
> > if we take the cuttings from the standard that you quoted, we have
> > that there's no way to assign to an unitialized pointer:
> >
> > int   i,  * pi;
> > pi = &i;   // pi - an invalid pointer value - is used. Undefined
> > behavior?
>
> I don't think so.  The *value* of pi is not used in the statement
> "pi = &i;" although the object pi might be said to be used.  The
> statement does not depend in any way on the previous value of pi.
>
> > I think the findings are enough for a defect report, because the
> > sentence "The effect of using an invalid pointer value (including
> > passint it to a deallocation function) is undefined" is incorrect.
>
> I think that the distinction between using an object and using
> the value of that object means that this is not a defect.

I agree.

Thank you very much James!

Regards
Kiril

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "Andrei Alexandrescu" <andrewalex@hotmail.com>
Date: Fri, 25 May 2001 04:59:55 GMT
Raw View
"James Dennett" <jdennett@acm.org> wrote in message
news:3AF1DA3C.B586BBC@acm.org...
> Barry Margolin wrote:
> >
> > In article <slrn9f2p8h.1p4.news/comp.std.c++@nightrunner.nmhq.net>,
> > Niklas Matthies <news/comp.std.c++@nmhq.net> wrote:
> > >The only way I see how this could be resolved satisfying both sides
> > >would be the introduction of some "copy-safe" pointer type. Something
> > >similar to uintptr_t in C99 could do the trick.
> >
> > Or to specify that the copying be done bit-wise, a la memcpy().  But
that
> > would presumably break containers that contain objects rather than
> > pointers, since their copy constructor or assignment operator wouldn't
be
> > run.
>
> We could just require that the Standard containers be (partially?)
> specialized for pointer types.  I think.


Um, I guess a better solution is to allow containers users to configure them
with a function that the container calls whenever it takes initiative in
destroying an element. By default that is a no-op, but it can be a Release()
function or a delete or a delete[] or whatever the user wants.

This is tricky however because the idiom cont.erase(remove(...)) doesn't
work anymore. The standard would have to define a function 'segregate' that
works much like remove, except it always uses swap instead of assignments.
This way, the elements after a call to segregate are the same, only
reordered. Then, when you call erase, the container correctly calls the
pre-destruction hook for all segregated elements.

Generic<Programming> on October will treat the subject of owning containers
featuring code with owning wrappers for STL containers, supporting
algorithms, examples of idomatic use, and caveats. Not that anyone cares,
sigh. I don't like Web publishing, people think it's rubbish :o(.


Andrei

--
Check out THE C++ Seminar:  3 Days with 5 Experts
http://www.gotw.ca/cpp_seminar



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "Andrei Alexandrescu" <andrewalex@hotmail.com>
Date: Fri, 25 May 2001 10:42:33 GMT
Raw View
"James Dennett" <jdennett@acm.org> wrote in message
news:3AF1DA3C.B586BBC@acm.org...
> Barry Margolin wrote:
> >
> > In article <slrn9f2p8h.1p4.news/comp.std.c++@nightrunner.nmhq.net>,
> > Niklas Matthies <news/comp.std.c++@nmhq.net> wrote:
> > >The only way I see how this could be resolved satisfying both sides
> > >would be the introduction of some "copy-safe" pointer type. Something
> > >similar to uintptr_t in C99 could do the trick.
> >
> > Or to specify that the copying be done bit-wise, a la memcpy().  But
that
> > would presumably break containers that contain objects rather than
> > pointers, since their copy constructor or assignment operator wouldn't
be
> > run.
>
> We could just require that the Standard containers be (partially?)
> specialized for pointer types.  I think.


Um, I guess a better solution is to allow containers users to configure them
with a function that the container calls whenever it takes initiative in
destroying an element. By default that is a no-op, but it can be a Release()
function or a delete or a delete[] or whatever the user wants.

This is tricky however because the idiom cont.erase(remove(...)) doesn't
work anymore. The standard would have to define a function 'segregate' that
works much like remove, except it always uses swap instead of assignments.
This way, the elements after a call to segregate are the same, only
reordered. Then, when you call erase, the container correctly calls the
pre-destruction hook for all segregated elements.

Generic<Programming> on October will treat the subject of owning containers
featuring code with owning wrappers for STL containers, supporting
algorithms, examples of idomatic use, and caveats. Not that anyone cares,
sigh. I don't like Web publishing, people think it's rubbish :o(.


Andrei

--
Check out THE C++ Seminar:  3 Days with 5 Experts
http://www.gotw.ca/cpp_seminar



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: kavdeiv@mail.ru (Kiril Avdeiv)
Date: Fri, 25 May 2001 20:12:29 GMT
Raw View
James Dennett <jdennett@acm.org> wrote in message news:<3AF69057.1778277E@acm.org>...
> Assaf Lavie wrote:
> >
> > >IIRC that's not specified by the Standard.  Maybe it should
> > >be, or maybe it is and I've just missed it.
> >
> > Why do you make the assertion that copying deallocated pointers (not
> > de-referencing them) yields undefined behavior if it is not specified by the
> > standard?
>
> The fact that copying deallocated pointers yields undefined
> behaviour *is* clearly stated by the Standard.

James, I am very grateful if you show where it is stated.

Thank you
Kiril

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "James Kuyper Jr." <kuyper@wizard.net>
Date: Fri, 25 May 2001 23:21:37 GMT
Raw View
Kiril Avdeiv wrote:
>
> James Dennett <jdennett@acm.org> wrote in message news:<3AF69057.1778277E@acm.org>...
> > Assaf Lavie wrote:
> > >
> > > >IIRC that's not specified by the Standard.  Maybe it should
> > > >be, or maybe it is and I've just missed it.
> > >
> > > Why do you make the assertion that copying deallocated pointers (not
> > > de-referencing them) yields undefined behavior if it is not specified by the
> > > standard?
> >
> > The fact that copying deallocated pointers yields undefined
> > behaviour *is* clearly stated by the Standard.
>
> James, I am very grateful if you show where it is stated.

3.6.3.2 says: "... 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."

Therefore, if you copy a deallocated pointer in any way that uses the
value, such as:

 p = q;

then the copy allows undefined behavior. If you copy it in a manner that
doesn't use the value, such as

 memcpy(&p, &q, sizeof(p));

then it's perfectly safe.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: James Dennett <jdennett@acm.org>
Date: Fri, 25 May 2001 23:31:04 GMT
Raw View
Kiril Avdeiv wrote:
>
> James Dennett <jdennett@acm.org> wrote in message news:<3AF69057.1778277E@acm.org>...
> > Assaf Lavie wrote:
> > >
> > > >IIRC that's not specified by the Standard.  Maybe it should
> > > >be, or maybe it is and I've just missed it.
> > >
> > > Why do you make the assertion that copying deallocated pointers (not
> > > de-referencing them) yields undefined behavior if it is not specified by the
> > > standard?
> >
> > The fact that copying deallocated pointers yields undefined
> > behaviour *is* clearly stated by the Standard.
>
> James, I am very grateful if you show where it is stated.

5.3.5/4 contains "Note: the value of a pointer that refers to
deallocated storage is indeterminate." but I don't think that's
the piece I want.

Ah...  3.7.3.2/4 is the one: "If the argument given to a
deallocation function in the standard library is a pointer that
is not the null pointer value (4.10), the deallocation function
shall deallocate the store 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 passint it to a deallocation function) is undefined."

There's a footnote (33) which points out that "On some
implementations, it causes a system-generated runtime fault."

If you agree that copying a pointer is a "use" of the pointer,
this clearly states that

int *p(new int);
delete p;  // invalidates p
int *q(p); // use of invalid pointer

invokes undefined behaviour.

-- James Dennett

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "James Kuyper Jr." <kuyper@wizard.net>
Date: Wed, 9 May 2001 02:25:15 GMT
Raw View
Brian Hanley wrote:
...
> My question was, is a pointer-to-member-function necessarily considered
> a plain old data (POD) type?

Yes - section 3.9p10 defines POD types as including scalar types, and
scalar types as include pointer to member types.

> Am I mistaken that calling memcpy() on a (valid) instance of a class with
> virtual functions does not necessarily yield a valid copy?

No, per 3.9p2, that guarantee is only made for objects of POD type.

...
> My point, then, is that specializing standard containers on pointer types in
> order to use memcpy() ...
> - Might allow us to copy invalid regular pointers, but
> - Might break the copying of valid pointers-to-member-functions.

Luckily, pointers-to-member-functions are POD types.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: James Dennett <jdennett@acm.org>
Date: Mon, 7 May 2001 12:18:39 GMT
Raw View
Assaf Lavie wrote:
>
> >IIRC that's not specified by the Standard.  Maybe it should
> >be, or maybe it is and I've just missed it.
>
> Why do you make the assertion that copying deallocated pointers (not
> de-referencing them) yields undefined behavior if it is not specified by the
> standard?

The fact that copying deallocated pointers yields undefined
behaviour *is* clearly stated by the Standard.

The thing that the Standard does not specify (and I hoped this
was clear from the context in which my words were originally
found, as a reply to a post of Markus Schaaf) is how often a
std::vector might copy the objects it contains.

It's possible that we might be able to look at the exception-
safety guarantees and try to conclude that copying is only
allowed during certain operations, but I'm not confident of
that and even if it is possible, it's a kludge.

-- James Dennett.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "Brian Hanley" <brian.hanley@level3.com>
Date: Tue, 8 May 2001 12:58:11 GMT
Raw View
"James Dennett" <jdennett@acm.org> wrote in message
news:3AF69057.1778277E@acm.org...
[SNIP]
> The fact that copying deallocated pointers yields undefined
> behaviour *is* clearly stated by the Standard.
>
> The thing that the Standard does not specify (and I hoped this
> was clear from the context in which my words were originally
> found, as a reply to a post of Markus Schaaf) is how often a
> std::vector might copy the objects it contains.
>
> It's possible that we might be able to look at the exception-
> safety guarantees and try to conclude that copying is only
> allowed during certain operations, but I'm not confident of
> that and even if it is possible, it's a kludge.
>
> -- James Dennett.

I don't know if this has been addressed yet (no pun intended :) ...
my newsreader may be missing some posts:

You suggested that perhaps we could specialize the Standard
containers for pointer types, and use memcpy() to safely copy
invalid pointers ...

I know it's contrived, but what about pointers to member functions?

Is there any reason why one couldn't have a container with pointers-
to-member-functions in it?

Pointers to member functions have to implement virtual dispatch ...
can compiler vendors give them non-trivial copy constructors?

If so, could memcpy() potentially produce a broken copy of such a
pointer?

(This also has interesting implications for what Valentin Bonnard said
about complexity guarantees ...)

Brian



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "James Kuyper Jr." <kuyper@wizard.net>
Date: Tue, 8 May 2001 16:10:28 GMT
Raw View
Brian Hanley wrote:
...
> You suggested that perhaps we could specialize the Standard
> containers for pointer types, and use memcpy() to safely copy
> invalid pointers ...
>
> I know it's contrived, but what about pointers to member functions?
>
> Is there any reason why one couldn't have a container with pointers-
> to-member-functions in it?
>
> Pointers to member functions have to implement virtual dispatch ...
> can compiler vendors give them non-trivial copy constructors?
>
> If so, could memcpy() potentially produce a broken copy of such a
> pointer?

Pointers to members are very different from ordinary pointers. They
don't point directly at anything; you combine them with an actual object
to dereference the pointer. You can't deallocate the thing they point
at. As a result, they can't become invalid the way that ordinary
pointers do.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "Brian Hanley" <brian.hanley@level3.com>
Date: Tue, 8 May 2001 21:03:28 GMT
Raw View
"James Kuyper Jr." <kuyper@wizard.net> wrote in message
news:3AF7F543.D6399AF8@wizard.net...
[SNIP]
> Pointers to members are very different from ordinary pointers. They
> don't point directly at anything; you combine them with an actual object
> to dereference the pointer. You can't deallocate the thing they point
> at. As a result, they can't become invalid the way that ordinary
> pointers do.

I am aware of that ... I wasn't talking about copying invalid pointer-to-
member-functions. I can't see a way to invalidate a pointer-to-member-
function either.

I was talking about copying -- as you say, inherently valid -- pointer-to-
member-functions.

My question was, is a pointer-to-member-function necessarily considered
a plain old data (POD) type?

Am I mistaken that calling memcpy() on a (valid) instance of a class with
virtual functions does not necessarily yield a valid copy?

For example:

class A
{
    public:
    virtual void fn() {} // A is no longer a POD

    private:
    // ...
};

class B: public A
// ...

char byteRep[sizeof(A)]; // Not guaranteed to properly hold an "A" instance

In this case, you shouldn't use memcpy() to copy an object of type "A"
because
"A" is not a POD type.

My point, then, is that specializing standard containers on pointer types in
order to use memcpy() ...
- Might allow us to copy invalid regular pointers, but
- Might break the copying of valid pointers-to-member-functions.

(Given that if we specialize on T*, then the specialization picks up all the
possible
pointer types for the template parameter ... including
pointer-to-member-function.)

Brian



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: AssafLavie@hotmail.com ("Assaf Lavie")
Date: Mon, 7 May 2001 05:24:47 GMT
Raw View
>IIRC that's not specified by the Standard.  Maybe it should
>be, or maybe it is and I've just missed it.

Why do you make the assertion that copying deallocated pointers (not
de-referencing them) yields undefined behavior if it is not specified by the
standard?

Assaf Lavie



--
Posted from [192.115.106.236] by way of oe45.law10.hotmail.com [64.4.14.17]
via Mailgate.ORG Server - http://www.Mailgate.ORG

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Valentin.Bonnard@free.fr (Valentin Bonnard)
Date: Sat, 5 May 2001 12:10:03 GMT
Raw View
Dennis Yelle  wrote:

> There has recently been a long thread in another news.group about having
> pointers to deleted memory in a container, for example:
> =================================
> #include <vector>
> using namespace std;
>
> int main1()
> {
>   vector<int*> vi;
>   vi.push_back( new int);
>   delete vi[0];
>   return 0;
> }
> =================================
>
> The claim has been made that main1 above has undefined behavior.
> In order to fix it, someone proposed this:
>
> ==========================================
> #include <vector>
> using namespace std;
>
> int main2()
> {
>   vector<int*> vi;
>   vi.push_back( new int);
>   delete vi[0];
>   vi[0] = 0;
>   return 0;
> }
> ===========================================
>
> The claim was made that main2 also has undefined behavior.
> More precisely, the claim is that having a pointer to
> deleted memory in any standard container for even
> an instant is undefined behavior.

I would question this, on the ground that the exception
and complexity garanties of op[] don't (shouldn't if
they were correctly written, but the fact that complexity
garanties are completely broken is well-known) allow
any call to a copy constructor, so you get no undefined
behaviour. (Weak argument, I know.)

For the first case, you must only forbid calls to erased
objects copy contructors (this applies to both forms for
erase, clear, destructor, the lhs of assignements).

Seems easy.

> Also, how about set and map?
> Is intended that less<> work for deleted pointers?

No.

> Is it intended that set and map work properly when
> a deleted pointer is used as a key in a set or a map?

No.

> Can we get this clarified?

I bet it can and will be clarified.

  -- VB

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "James Kuyper Jr." <kuyper@wizard.net>
Date: Sat, 5 May 2001 12:11:58 GMT
Raw View
Markus Schaaf wrote:
...
> BTW: To test a pointers value, I don't even need to load it
> into any special register.

When you choose to write C rather than assembly language, you loose your
control over such features. If the implementation chooses to load a
pointer into an address register in order to test it, that's the
implementation's right; I suspect that it has a good reason, one that
would also constitute good programming practice for you if you were
writing in assembly code for the same platform.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Ron Natalie <ron@spamcop.net>
Date: Fri, 4 May 2001 21:24:25 GMT
Raw View

Markus Schaaf wrote:
>
> Completely agree with you. But there is no need to load a
> pointer's value into any special-purpose register just for
> copying. Keeping in mind, that there must be ways to copy
> values other than valid pointers anyhow.
>

If the goal were just to copy it, yes.  However, one would presume
that the reason it was loaded into a pointer variable was that
it might someday be used as a pointer:

 int* p;
 int* q;

 p = q;

 if(p) { ...

Of course we're now arguing if the explosion happens on the assignment
or the if, but its wrong either way.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "Markus Schaaf" <m.schaaf.exp-jun2001@gmx.de>
Date: Sat, 5 May 2001 00:04:27 GMT
Raw View
"Ron Natalie" <ron@spamcop.net> wrote:

> int* p;
> int* q;
>
> p =3D q;
>
> if(p) { ...
>
> Of course we're now arguing if the explosion happens on the assignment
> or the if, ...

Please refer to the article which started this thread. There
is no 'if' or anything else after that (possible) assignment.
BTW: To test a pointers value, I don't even need to load it
into any special register.

After thinking about the matter twice, it doesn't bother me
any more. If the standard demands that a pointer's value
has to be valid to use it in some way, even for nothing
but copying, that might be ok. I was just a little shocked
to find myself knowing nothing about this special problem.
Shame on me!

kind regards
=AB=20
--=20
PGP: 0x6F8F6E09 RSA/2048 E952 24D9 3096 F859 5CC8 BEBF 1D45 F357


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Barry Margolin <barmar@genuity.net>
Date: Sat, 5 May 2001 00:42:04 GMT
Raw View
In article <9cvft5$fk8qu$1@ID-3706.news.dfncis.de>,
Markus Schaaf <m.schaaf.exp-jun2001@gmx.de> wrote:
>"Ron Natalie" <ron@spamcop.net> wrote:
>
>> int* p;
>> int* q;
>>
>> p = q;
>>
>> if(p) { ...
>>
>> Of course we're now arguing if the explosion happens on the assignment
>> or the if, ...
>
>Please refer to the article which started this thread. There
>is no 'if' or anything else after that (possible) assignment.

So?  The standard needs specify all assignments, not just the ones that
don't have an 'if' or '*p' after it.  Either they're all valid or none of
them are.  The examples that I and Ron Natalie gave show why it's
appropriate for none of them to be valid -- by allowing assignments to use
address registers, you enable optimization.

--
Barry Margolin, barmar@genuity.net
Genuity, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Barry Margolin <barmar@genuity.net>
Date: Sat, 5 May 2001 12:07:52 GMT
Raw View
In article <9csn10$fafds$2@ID-3706.news.dfncis.de>,
Markus Schaaf <m.schaaf.exp-jun2001@gmx.de> wrote:
>Completely agree with you. But there is no need to load a
>pointer's value into any special-purpose register just for
>copying. Keeping in mind, that there must be ways to copy
>values other than valid pointers anyhow.

True, you can use regular data registers and perform bit-wise copies of
pointers.  But I think many compilers generate code that uses the pointer
registers for this because it's not unlikely that a pointer will be
dereferenced shortly after copying it, and if it's already in the right
kind of register it's not necessary to reload it.  Unless you want to
prohibit this optimization unless the compiler can prove that the value
will be dereferenced, you have to live with pointer assignments having to
obey the same restrictions as pointer dereferencing.

--
Barry Margolin, barmar@genuity.net
Genuity, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Thu, 3 May 2001 12:45:06 GMT
Raw View
On Thu,  3 May 2001 02:15:14 GMT, James Dennett <jdennett@acm.org>
wrote:

> > |        pc++;
>
> Syntactically fine, but not legal if pc = &ci (as written above).

It's valid.  See 5.7/4.  For pointer arithmetic, objects act like
arrays of size one.

John

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: scott douglass <sdouglass@arm.com>
Date: Thu, 3 May 2001 13:52:19 GMT
Raw View
James Dennett wrote:
> > [Someone unattributed qutoed the standard:]
> > | 8.3.1 Pointers
> > | [...]
> > | 2 [Example: the declarations
> > |
> > |      const int ci = 10, *pc = &ci, *const cpc = pc, **ppc;
> > |   [...]
> > |        pc++;
>
> Syntactically fine, but not legal if pc = &ci (as written above).

I think that's legal.  Afterwards 'pc[-1]' is fine but 'pc[0]' is not legal.
The 'pc++' puts 'pc' into the one-past-the-end-of-an-array state.  You might
argue that there's no array here, but 5.7/4 (about '+' and '-') says:

For the purposes of these operators, a pointer to a nonarray object behaves the
same as a pointer to the first element of an array of length one with the type
of the object as its element type.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Barry Margolin <barmar@genuity.net>
Date: Thu, 3 May 2001 15:49:26 GMT
Raw View
In article <9cqc9q$f169l$1@ID-3706.news.dfncis.de>,
Markus Schaaf <m.schaaf.exp-jun2001@gmx.de> wrote:
>"James Dennett" <jdennett@acm.org> wrote:
>> Copying an invalid pointer is undefined behaviour.
>
>This is absolutely new to me. But I have to admit, that
>I'm not one of those knowing the standard by heart. You
>mean that
>
>    int main() {
>        int *p, *q;
>        p = q;
>    }
>
>is undefined behaviour? Really? I can't believe this.
>But if it is true, I'm a strong supporter of having this
>changed.

Yes, it's true.  I believe it has been since C90, and C++ simply adopted it
like most other C features that don't conflict with C++'s goals.

Some types of processors have dedicated pointer registers or instructions
for manipulating pointers, and pointers may be checked for validity when
they are used.  This provision in the standard allows these mechanisms to
be used when accessing pointers.

Actually, there's another provision that isn't even specific to pointers.
I believe any reference to an indeterminate value results in undefined
behavior, e.g.:

int main() {
  int p, q;
  p = q;
}

Since q's value is indeterminate, any reference to it is undefined
behavior.

--
Barry Margolin, barmar@genuity.net
Genuity, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: James Dennett <jdennett@acm.org>
Date: Thu, 3 May 2001 20:32:37 GMT
Raw View
John Potter wrote:
>
> On Thu,  3 May 2001 02:15:14 GMT, James Dennett <jdennett@acm.org>
> wrote:
>
> > > |        pc++;
> >
> > Syntactically fine, but not legal if pc = &ci (as written above).
>
> It's valid.  See 5.7/4.  For pointer arithmetic, objects act like
> arrays of size one.

Live and learn; John is quite right, that's what the Standard
says.  So, I was wrong on one of my two clarifications; what
about the other one?!  Surely I'm safe to say that copying a
pointer of indeterminate value is undefined?

-- James Dennett.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: news/comp.std.c++@nmhq.net (Niklas Matthies)
Date: Thu, 3 May 2001 20:34:02 GMT
Raw View
On Thu,  3 May 2001 01:49:13 GMT, Markus Schaaf <m.schaaf.exp-jun2001@gmx=
.de> wrote:
[=B7=B7=B7]
> > Copying an invalid pointer is undefined behaviour.
>=20
> This is absolutely new to me. But I have to admit, that
> I'm not one of those knowing the standard by heart. You
> mean that
>=20
>     int main() {=20
>         int *p, *q;
>         p =3D q;
>     }
>=20
> is undefined behaviour? Really? I can't believe this.
> But if it is true, I'm a strong supporter of having this
> changed.

There were hardware architectures in the past (and probably still
existing) that check the validness of an address when loading it into an
address register, and raise some hardware exception if it is invalid.
And "valid" here can coincide with the meaning that one usually
associates with new/delete. Although the currently most widespread
architectures don't do anything like this, ones that do such checking
have usually good reasons to do so (e.g. safety-critical applications
where you _do_ want to immediately notice the use of an invalid memory
address), and arguably C++ should not disfavor such architectures.

Of course, even if there were more specific guarantees as to when
container elements may be copied, it would still be undefined behavior
to resize a vector of pointers that contains an uninitialized pointer
value. This puts C++ at a disadvantage on architectures where copying of
such values is harmless.

The only way I see how this could be resolved satisfying both sides
would be the introduction of some "copy-safe" pointer type. Something
similar to uintptr_t in C99 could do the trick.

-- Niklas Matthies

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Barry Margolin <barmar@genuity.net>
Date: Thu, 3 May 2001 21:15:45 GMT
Raw View
In article <slrn9f2p8h.1p4.news/comp.std.c++@nightrunner.nmhq.net>,
Niklas Matthies <news/comp.std.c++@nmhq.net> wrote:
>The only way I see how this could be resolved satisfying both sides
>would be the introduction of some "copy-safe" pointer type. Something
>similar to uintptr_t in C99 could do the trick.

Or to specify that the copying be done bit-wise, a la memcpy().  But that
would presumably break containers that contain objects rather than
pointers, since their copy constructor or assignment operator wouldn't be
run.

--
Barry Margolin, barmar@genuity.net
Genuity, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Fri, 4 May 2001 00:23:33 GMT
Raw View
On Thu,  3 May 2001 20:32:37 GMT, James Dennett <jdennett@acm.org>
wrote:

> So, I was wrong on one of my two clarifications; what
> about the other one?!  Surely I'm safe to say that copying a
> pointer of indeterminate value is undefined?

Something you said in this newsgroup went unchallenged and you wonder
if it was correct?  :)

Let's get back to the real problem.

void f () {
   vector<int*> v;
   v.push_back(new int(42));
   v.push_back(new int(69));
   delete v[0];
   v.erase(v.begin());
   }

It would be valid to implement erase as

   erase (iterator pos) {
      rotate(pos, pos + 1, end());
      destroy(&*end());
      -- size;
      }

That gives undefined behavior to the above code because it copies the
deleted pointer.

I think that I am opposed to one of the goals of making it easier to
write C++ libraries.  How about making it harder to implement so that
we can use them sensibly without worrying about this nonsense?

John

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "Sorin Jianu" <sorinj@real.com>
Date: Fri, 4 May 2001 00:23:25 GMT
Raw View
"Barry Margolin" <barmar@genuity.net> wrote in message
news:k_eI6.10$Ip3.481@burlma1->
> Yes, it's true.  I believe it has been since C90, and C++ simply adopted
it
> like most other C features that don't conflict with C++'s goals.
>
>
> Actually, there's another provision that isn't even specific to pointers.
> I believe any reference to an indeterminate value results in undefined
> behavior, e.g.:
>
> int main() {
>   int p, q;
>   p = q;
> }
>

could you please point out where in the standard says so?

Sorin


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: James Dennett <jdennett@acm.org>
Date: Fri, 4 May 2001 00:23:55 GMT
Raw View
Barry Margolin wrote:
>
> In article <slrn9f2p8h.1p4.news/comp.std.c++@nightrunner.nmhq.net>,
> Niklas Matthies <news/comp.std.c++@nmhq.net> wrote:
> >The only way I see how this could be resolved satisfying both sides
> >would be the introduction of some "copy-safe" pointer type. Something
> >similar to uintptr_t in C99 could do the trick.
>
> Or to specify that the copying be done bit-wise, a la memcpy().  But that
> would presumably break containers that contain objects rather than
> pointers, since their copy constructor or assignment operator wouldn't be
> run.

We could just require that the Standard containers be (partially?)
specialized for pointer types.  I think.

-- James Dennett

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "Markus Schaaf" <m.schaaf.exp-jun2001@gmx.de>
Date: Fri, 4 May 2001 00:23:48 GMT
Raw View
"Niklas Matthies" <news/comp.std.c++@nmhq.net> wrote:

>There were hardware architectures in the past (and probably still
>existing) that check the validness of an address when loading it into an
>address register, and raise some hardware exception if it is invalid.

Yes. I know about such architectures.

>And "valid" here can coincide with the meaning that one usually
>associates with new/delete. Although the currently most widespread
>architectures don't do anything like this, ones that do such checking
>have usually good reasons to do so (e.g. safety-critical applications
>where you _do_ want to immediately notice the use of an invalid memory
>address), and arguably C++ should not disfavor such architectures.

Completely agree with you. But there is no need to load a
pointer's value into any special-purpose register just for
copying. Keeping in mind, that there must be ways to copy
values other than valid pointers anyhow.

kind regards
=AB=20
--=20
PGP: 0x6F8F6E09 RSA/2048 E952 24D9 3096 F859 5CC8 BEBF 1D45 F357


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Dennis Yelle <dennis51@jps.net>
Date: Wed, 2 May 2001 20:24:50 GMT
Raw View
There has recently been a long thread in another news.group about having
pointers to deleted memory in a container, for example:
=================================
#include <vector>
using namespace std;

int main1()
{
  vector<int*> vi;
  vi.push_back( new int);
  delete vi[0];
  return 0;
}
=================================

The claim has been made that main1 above has undefined behavior.
In order to fix it, someone proposed this:

==========================================
#include <vector>
using namespace std;

int main2()
{
  vector<int*> vi;
  vi.push_back( new int);
  delete vi[0];
  vi[0] = 0;
  return 0;
}
===========================================

The claim was made that main2 also has undefined behavior.
More precisely, the claim is that having a pointer to
deleted memory in any standard container for even
an instant is undefined behavior.

Everyone seems to agree that all existing compilers and
libraries will, in fact, do the right thing.

So, can we get the C++ standard changed to clearly state
that functions like main1 and main2 above are OK?

Also, how about set and map?
Is intended that less<> work for deleted pointers?
Is it intended that set and map work properly when
a deleted pointer is used as a key in a set or a map?
Can we get this clarified?

Dennis Yelle
--
I am a computer programmer and I am looking for a job.
There is a link to my resume here:
http://table.jps.net/~vert/

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "Markus Schaaf" <m.schaaf.exp-jun2001@gmx.de>
Date: Wed, 2 May 2001 22:38:03 GMT
Raw View
"Dennis Yelle" <dennis51@jps.net> wrote:

> int main1()
> {
>   vector<int*> vi;
>   vi.push_back( new int);
>   delete vi[0];
>   return 0;
> }

> int main2()
> {
>   vector<int*> vi;
>   vi.push_back( new int);
>   delete vi[0];
>   vi[0] = 0;
>   return 0;
> }

> So, can we get the C++ standard changed to clearly state
> that functions like main1 and main2 above are OK?

Your examples make no sense, because you are allowed to put
what you want in 'vi'. But I'll assume 'vi' is of type
'vector< smart_ptr< int > >', with 'smart_ptr< int >' calling
'delete' on destruction. Maybe this is closer to your
intentions.

Is 'main1' ok then? Never ever. You can't delete a pointer
twice. The standard is very definite about that. And I don't
like the idea of having it changed in this point.

What about 'main2'? Well, it may be ok IMO, presuming that
there is no possibility for throwing an exception between
'delete vi[0]' and the statement following 'vi[0]=0'. I'm
aware that this is not exactly what is written in the
standard, because there is (for example) no guarantee that
'operator[]' doesn't throw. In fact it seems to be intended
that it possibly throws 'out_of_range' or something similar.
(Not mentioning 'smart_ptr< int >::operator=" here.)

So the questions are: Must a container's 'operator[]' be
expected to throw, if its argument is valid (i.e. not out
of range)? Must the same 'operator[]' be expected to call
a destructor?

AFAIK both questions have to be answered 'yes'. (I don't
think there are implementations out there worth mentioning,
that do anything of the above.)

But all of that doesn't really matter. In any actual
programme, you would do both steps at once, in a member
function of 'smart_ptr<>' called 'release' or something
like that.

> Also, how about set and map?
> Is intended that less<> work for deleted pointers?

Why not? But this depends on what 'less<>' does. As long
as it doesn't dereference the pointer, it will work. So
'less< int* >( p, q )' should work with every p and q,
regardless of their values. The same applies to any other
simple pointer type.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: James Dennett <jdennett@acm.org>
Date: Wed, 2 May 2001 23:12:26 GMT
Raw View
Markus Schaaf wrote:
>
> "Dennis Yelle" <dennis51@jps.net> wrote:
>
> > int main1()
> > {
> >   vector<int*> vi;
> >   vi.push_back( new int);
> >   delete vi[0];
> >   return 0;
> > }
>
> > int main2()
> > {
> >   vector<int*> vi;
> >   vi.push_back( new int);
> >   delete vi[0];
> >   vi[0] = 0;
> >   return 0;
> > }
>
> > So, can we get the C++ standard changed to clearly state
> > that functions like main1 and main2 above are OK?
>
> Your examples make no sense, because you are allowed to put
> what you want in 'vi'.

The example makes sense to me.  You can put only pointers
to ints (or null pointers) into vi.  vi is allowed to copy
those pointers.  Copying an invalid pointer is undefined
behaviour.  When copies are made is not specified.  So,
leaving a pointer which has been deleted in a container
is potentially problematic.

Even vi[0] = 0 is allowed to copy vi[0] (though of course
it is not required to), and so it seems that the only
safe way to proceed is to copy vi[0], set vi[0] = 0, and
then delete the copied pointer.  It would seem desirable
that the Standard does not mandate this dance.

-- James Dennett

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "Markus Schaaf" <m.schaaf.exp-jun2001@gmx.de>
Date: Thu, 3 May 2001 01:49:13 GMT
Raw View
"James Dennett" <jdennett@acm.org> wrote:

> The example makes sense to me.  You can put only pointers
> to ints (or null pointers) into vi.  vi is allowed to copy
> those pointers.

It seems, I've missed the point slightly. ;-) But it wasn't
obvious though. OTOH there are certain restrictions
concerning copying. Ok, not copying, but invalidation of
iterators and references owing to copying. IIRC no copying
takes place, if a vector's capacity needn't change.

> Copying an invalid pointer is undefined behaviour.

This is absolutely new to me. But I have to admit, that
I'm not one of those knowing the standard by heart. You
mean that

    int main() {
        int *p, *q;
        p = q;
    }

is undefined behaviour? Really? I can't believe this.
But if it is true, I'm a strong supporter of having this
changed.

However it may be, I've found the following:

| 8.3.1 Pointers
| [...]
| 2 [Example: the declarations
|
|      const int ci = 10, *pc = &ci, *const cpc = pc, **ppc;
|      int i, *p, *const cp = &i;
|
|   declare ci, a constant integer; pc, a pointer to a constant
|   integer; cpc, a constant pointer to a constant integer, ppc,
|   a pointer to a pointer to a constant integer; i, an integer;
|   p, a pointer to integer; and cp, a constant pointer to integer.
|   The value of ci, cpc, and cp cannot be changed after
|   initialization. The value of pc can be changed, and so can the
|   object pointed to by cp. Examples of some correct operations are
|
|        i = ci;
|        *cp = ci;
|        pc++;
|        pc = cpc;
|        pc = p;               <------- note especially this one
|        ppc = &pc;
|   [...]

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: James Dennett <jdennett@acm.org>
Date: Thu, 3 May 2001 02:15:14 GMT
Raw View
Markus Schaaf wrote:
>
> "James Dennett" <jdennett@acm.org> wrote:
>
> > The example makes sense to me.  You can put only pointers
> > to ints (or null pointers) into vi.  vi is allowed to copy
> > those pointers.
>
> It seems, I've missed the point slightly. ;-) But it wasn't
> obvious though. OTOH there are certain restrictions
> concerning copying. Ok, not copying, but invalidation of
> iterators and references owing to copying. IIRC no copying
> takes place, if a vector's capacity needn't change.

IIRC that's not specified by the Standard.  Maybe it should
be, or maybe it is and I've just missed it.

> > Copying an invalid pointer is undefined behaviour.
>
> This is absolutely new to me. But I have to admit, that
> I'm not one of those knowing the standard by heart. You
> mean that
>
>     int main() {
>         int *p, *q;
>         p = q;
>     }
>
> is undefined behaviour? Really? I can't believe this.
> But if it is true, I'm a strong supporter of having this
> changed.
>
> However it may be, I've found the following:
>
> | 8.3.1 Pointers
> | [...]
> | 2 [Example: the declarations
> |
> |      const int ci = 10, *pc = &ci, *const cpc = pc, **ppc;
> |      int i, *p, *const cp = &i;
> |
> |   declare ci, a constant integer; pc, a pointer to a constant
> |   integer; cpc, a constant pointer to a constant integer, ppc,
> |   a pointer to a pointer to a constant integer; i, an integer;
> |   p, a pointer to integer; and cp, a constant pointer to integer.
> |   The value of ci, cpc, and cp cannot be changed after
> |   initialization. The value of pc can be changed, and so can the
> |   object pointed to by cp. Examples of some correct operations are

I believe that the intention is to show operations which are
correct inasmuch as they are syntatically valid and have sane
types, but not to imply that they are valid if there are no
assignments between the declarations above and the statements
below.

> |
> |        i = ci;
> |        *cp = ci;
> |        pc++;

Syntactically fine, but not legal if pc = &ci (as written above).

> |        pc = cpc;
> |        pc = p;               <------- note especially this one

Syntactically fine, but not legal if p is indeterminate.

> |        ppc = &pc;
> |   [...]

-- James Dennett

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]