Topic: Invalid pointer values
Author: alfps@start.no (Alf P. Steinbach)
Date: Sun, 9 Oct 2005 07:41:18 GMT Raw View
Can it be proven from the standard that the following code is Undefined
Behavior, or alternatively, can a convincing half-formal case be made?
#include <iostream> // std::cout
#include <ostream> // <<, std::endl
int* wrongAnswer()
{
int x = 43;
return &x;
}
int main()
{
int* p = wrongAnswer();
std::cout << *p << std::endl; // Not necessarily 43...
}
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Sun, 9 Oct 2005 16:10:53 GMT Raw View
Alf P. Steinbach wrote:
> Can it be proven from the standard that the following code is Undefined
> Behavior, or alternatively, can a convincing half-formal case be made?
>
> #include <iostream> // std::cout
> #include <ostream> // <<, std::endl
>
> int* wrongAnswer()
> {
> int x = 43;
> return &x;
> }
>
> int main()
> {
> int* p = wrongAnswer();
> std::cout << *p << std::endl; // Not necessarily 43...
> }
>
If I interpret the standard correctly, the standard specify that this is
UB because of:
3.7.2/1 The storage for [local objects with automatic static duration]
lasts until the block in which they are created exits.
3.8/1 The lifetime of an object of type T ends when [...] the storage
which the object occupies is reused or released.
3.8/3 The properties ascribed to objects throughout this International
Standard apply for a given object only during its lifetime.
So the expression *p would refer to an l-value whose lifetime has ended
but any use of it is not covered by the standard (and that's practically
the definition of UB).
Ganesh
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: "Peter Dimov" <pdimov@gmail.com>
Date: Sun, 9 Oct 2005 11:11:34 CST Raw View
Alf P. Steinbach wrote:
> Can it be proven from the standard that the following code is Undefined
> Behavior, or alternatively, can a convincing half-formal case be made?
>
> #include <iostream> // std::cout
> #include <ostream> // <<, std::endl
>
> int* wrongAnswer()
> {
> int x = 43;
> return &x;
> }
>
> int main()
> {
> int* p = wrongAnswer();
Half-formal case: the pointer value that is returned from wrongAnswer
refers to storage that no longer "lasts" (3.7.2/1). This strongly
suggests that this pointer value is invalid.
Pointer values that refer to "deallocated" storage (3.7.3.2/4) are
invalid and "The effect of using an invalid pointer value is undefined
(footnote: On some implementations, it causes a system-generated
runtime fault.)"
> std::cout << *p << std::endl; // Not necessarily 43...
90% proven: The lifetime of *p has ended and the lvalue to rvalue
conversion is undefined behavior (3.8/6).
> }
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: "Greg Herlihy" <greghe@pacbell.net>
Date: Sun, 9 Oct 2005 16:59:21 CST Raw View
Alf P. Steinbach wrote:
> Can it be proven from the standard that the following code is Undefined
> Behavior, or alternatively, can a convincing half-formal case be made?
>
> #include <iostream> // std::cout
> #include <ostream> // <<, std::endl
>
> int* wrongAnswer()
> {
> int x = 43;
> return &x;
> }
>
> int main()
> {
> int* p = wrongAnswer();
> std::cout << *p << std::endl; // Not necessarily 43...
> }
If "the standard" includes the C language standard, then the answer is
unambiguous: "If an object is referred to outside of its
lifetime, the behavior is undefined." 6.2.4/2 (ISO/IEC 9899:TC2). Of
course the sample program is not a C, but a C++ program - but how much
of a difference does that really make? After all, wrongAnswer could
just as easily be a C function, and, name mangling aside, would it
compile any differently in C than in C++?
C++, I believe, retains compatibility with C's memory model, but also
further extends and refines it, adding dynamic allocations of class
types in particular. As a consequence, C's blanket statement about
accesses and object lifetimes and undefined behavior no longer holds in
all cases in C++. But none of the exceptions that the C++ standard
cites (which seem to pertain to only non-POD types) would appear to
have any relevance to the sample program above. So I would conclude
that behavior of the program after deferencing p in the second line of
main, is not defined.
Greg
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: kuyper@wizard.net
Date: Mon, 10 Oct 2005 10:31:14 CST Raw View
Greg Herlihy wrote:
> Alf P. Steinbach wrote:
> > Can it be proven from the standard that the following code is Undefined
> > Behavior, or alternatively, can a convincing half-formal case be made?
> >
> > #include <iostream> // std::cout
> > #include <ostream> // <<, std::endl
> >
> > int* wrongAnswer()
> > {
> > int x = 43;
> > return &x;
> > }
> >
> > int main()
> > {
> > int* p = wrongAnswer();
> > std::cout << *p << std::endl; // Not necessarily 43...
> > }
>
> If "the standard" includes the C language standard, then the answer is
> unambiguous: "If an object is referred to outside of its
> lifetime, the behavior is undefined." 6.2.4/2 (ISO/IEC 9899:TC2). Of
> course the sample program is not a C, but a C++ program - but how much
> of a difference does that really make?
A lot. The C++ standard incorporates the C standard by reference, but
not wholesale; only parts of it are so incorporated. The main part so
incorporated is the C standard library, but even there it's
incorporated with modifications that are detailed in section C.2. For
the language itself, the description provided in the C++ standard is
intended to be basically complete; if the C standard says something
that the C++ standard does not, what the C standard says has nothing to
do with what the code means when interpreted by an implementation of
C++.
In this particular case, C++ has chosen a different way of saying this
than the C standard; I won't go into the details, since Peter Dimov has
already provided them.
> ... After all, wrongAnswer could
> just as easily be a C function, and, name mangling aside, would it
> compile any differently in C than in C++?
In general, yes, - see section C.1 of the C++ standard for a list of
differences between the two languages.
Keep in mind that since the behavior of this particular code is
undefined according to either standard, the result of using a C
implementation to translate this code could be the same as the result
of using a C++ implementation; it could also be quite different. In
particular, it could be the same using an implementation of Fortran, or
Lisp, or Java.
> C++, I believe, retains compatibility with C's memory model,
That's essentially true, but it's true only insofar as the C++ standard
actually says so; if you can't find text supporting a given assertion
in the C++ standard, finding relevant text in the C standard merely
serves to point out a difference between the two languages; it doesn't
make that assertion true for programs translated by an implementation
of C++.
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]