address of references to pointers

S

Stein Gulbrandsen

Is this legal C++?
or am I dereferencing posssibly invalid addresses here?

#include <vector>
struct C{};

int main () {
C* c;
C* a;

c = &a[0];

std::vector<C> v;
c = &*v.begin();

C& r = v.front();
c = &r;
}
 
J

John Carson

Stein Gulbrandsen said:
Is this legal C++?
or am I dereferencing posssibly invalid addresses here?

#include <vector>
struct C{};

int main () {
C* c;
C* a;

c = &a[0];

Illegal. a contains random junk; it does not point to valid memory.
std::vector<C> v;
c = &*v.begin();

Likewise illegal. v.begin() doesn't point to anything valid so you shouldn't
dereference it.
 
B

Ben Pope

Stein said:
Is this legal C++?
or am I dereferencing posssibly invalid addresses here?

#include <vector>
struct C{};

int main () {
C* c;
C* a;

// never leave pointers (or anything!) uninitialised.
c = &a[0];

// a is an uninitialised pointer to C, not an array of C.
// you're not allowed to dereference it.
// undefined behaviour follows.
std::vector<C> v;
c = &*v.begin();

// prefer std::vector said:
C& r = v.front();
c = &r;
}


Ben Pope
 
S

Stein Gulbrandsen

John Carson said:
Stein Gulbrandsen said:
Is this legal C++?
or am I dereferencing posssibly invalid addresses here?
c = &a[0];

Illegal. a contains random junk; it does not point to valid memory.
...
std::vector<C> v;
c = &*v.begin();

Likewise illegal. v.begin() doesn't point to anything valid so you shouldn't
dereference it.
...
C& r = v.front();

Illegal.

Thanks, that is what I would also think. So, if I understand things
right, all the 8 numbered lines below are illegal (undefined
behaviour). Nevertheless, it compiles silently (except for Sun
compiler warning about the reference to non-const at 8) and runs "OK"
(producing 8 zeroes on cout) on Sun WS C++, SGI Mipspro C++, Microsoft
Visual C++/.net, and g++.

It seems that no dereferencing is actually taking place.
Is this just by chance, because of some implementation details of the
compilers, or are any of these lines actuallly legal C++?

#include <vector>
#include <iostream>
class C{}; C* c = 0; // C is defined
class D; D* d = 0; // D is not defined
std::vector<int> v; // empty

int main () {
D& r = *d; // 1a
std::cout << &r << " " // 1b
<< &*static_cast<D*>(0) << " " // 2
<< &*d << " " // 3
<< &c[0] << " " // 4
<< &0[static_cast<C*>(0)] << " "// 5
<< &v[0] << " " // 6
<< &*v.begin() << " " // 7
<< &std::vector<C>().front() // 8
<< "\n";
}
 
C

Csaba

John Carson said:
Stein Gulbrandsen said:
Is this legal C++?
or am I dereferencing posssibly invalid addresses here?
c = &a[0];

Illegal. a contains random junk; it does not point to valid memory.
...
std::vector<C> v;
c = &*v.begin();

Likewise illegal. v.begin() doesn't point to anything valid so you
shouldn't dereference it.
...
C& r = v.front();

Illegal.

Thanks, that is what I would also think. So, if I understand things
right, all the 8 numbered lines below are illegal (undefined
behaviour). Nevertheless, it compiles silently (except for Sun
compiler warning about the reference to non-const at 8) and runs "OK"
(producing 8 zeroes on cout) on Sun WS C++, SGI Mipspro C++, Microsoft
Visual C++/.net, and g++.

It seems that no dereferencing is actually taking place.
Is this just by chance, because of some implementation details of the
compilers, or are any of these lines actuallly legal C++?

#include <vector>
#include <iostream>
class C{}; C* c = 0; // C is defined
class D; D* d = 0; // D is not defined
std::vector<int> v; // empty

int main () {
D& r = *d; // 1a
std::cout << &r << " " // 1b
<< &*static_cast<D*>(0) << " " // 2
<< &*d << " " // 3
<< &c[0] << " " // 4

In other words, this is taking the address of a value obtained from
dereferencing a NULL pointer, just like

& * (c + 0), where c==0.

Mybe the compiler just "cancels out" the dereferencing with the address-
of operator. But is it allowed to do that ?
<< &0[static_cast<C*>(0)] << " "// 5
<< &v[0] << " " // 6
<< &*v.begin() << " " // 7
<< &std::vector<C>().front() // 8
<< "\n";
}

STLPort with _STLP_DEBUG doesn't agree with line 6, throwing a debug
assert. In fact, if you replace &v[0] with &v.at(0), it'll throw a
std::eek:ut_of_range. So Line 6 is clearly not kosher, neither is 7 nor 8.

The program runs "OK" because all the STL implementations probably use a
pointer for the iterator of vector. In the Dinkumware STL supplied with
VC 7.1 (.NET 2003) , vector is implemented using three pointers _Myfirst,
_Mylast, _Myend. These are all NULL in a default-constructed vector.

operator[] is *( begin() + offset ), and begin() is just _Mybegin. The
compiler probably "sees through" that the result of dereferencing a NULL
pointer (ouch) is passed to the address-of operator.
 
B

benben

c = &a[0];
Illegal. a contains random junk; it does not point to valid memory.

I thought that statement doesn't dereference anything at all...merely
assigning the same random junk from a to c...just equivalent to

c = a + 0;

or just

c = a;

Regards,
Ben
 
B

benben

benben said:
c = &a[0];

Illegal. a contains random junk; it does not point to valid memory.

I thought that statement doesn't dereference anything at all...merely
assigning the same random junk from a to c...just equivalent to

c = a + 0;

or just

c = a;

Regards,
Ben

Well, thinking more, I might have mistaken...

&a[0] is equivalent to &(*(a + 0)) which is equivalent to &*a so there
is a dereference if the compiler doesn't optimize off the operator pair...

I think the result is UB...

Regards,
Ben
 
J

John Carson

Stein Gulbrandsen said:
John Carson said:
Stein Gulbrandsen said:
Is this legal C++?
or am I dereferencing posssibly invalid addresses here?
c = &a[0];

Illegal. a contains random junk; it does not point to valid memory.
...
std::vector<C> v;
c = &*v.begin();

Likewise illegal. v.begin() doesn't point to anything valid so you
shouldn't dereference it.
...
C& r = v.front();

Illegal.

Thanks, that is what I would also think.

If you run it in Debug mode in VC++ 8.0, then

c = &a[0];

produces

"Run-time Check Failure #3 - the variable 'a' is being used without being
defined."

If this line is commented out, then

c = &*v.begin();

produces

"Debug Assertion Failed!" following by "Expression: vector iterator is not
dereferencable"

If this line is commented out, then

C& r = v.front();

produces the same "Expression: vector iterator is not dereferencable" error.

In release mode,

c = &a[0];

"works" but

c = &*v.begin();

and

C& r = v.front();

crash the program (running on XP Home, SP2).

So, if I understand things
right, all the 8 numbered lines below are illegal (undefined
behaviour).
Yes.

Nevertheless, it compiles silently (except for Sun
compiler warning about the reference to non-const at 8) and runs "OK"
(producing 8 zeroes on cout) on Sun WS C++, SGI Mipspro C++, Microsoft
Visual C++/.net, and g++.

#include <vector>
#include <iostream>
class C{}; C* c = 0; // C is defined
class D; D* d = 0; // D is not defined
std::vector<int> v; // empty

int main () {
D& r = *d; // 1a
std::cout << &r << " " // 1b
<< &*static_cast<D*>(0) << " " // 2
<< &*d << " " // 3
<< &c[0] << " " // 4
<< &0[static_cast<C*>(0)] << " "// 5
<< &v[0] << " " // 6
<< &*v.begin() << " " // 7
<< &std::vector<C>().front() // 8
<< "\n";
}

Each of 6-8 crashes in Release mode with VC++ 8 and Windows XP Home SP2.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top