Why there is no memory access violation?

A

aling

Have following code snip:

struct struc {
int member1;
int member2;
} ;
printf("&((struc*)0)->member2=%p\n", &((struc*)0)->member2);

In VC7.1, the output is 4, the offset of member2 in struc.

I wonder why there is no memory access violation for
"((struc*)0)->member2" ?
And why the output is the offset of struc?

what's the output in pure C compiler? I have no C compiler at hand now.
 
J

Jonathan Mcdougall

aling said:
Have following code snip:

struct struc {
int member1;
int member2;
} ;
printf("&((struc*)0)->member2=%p\n", &((struc*)0)->member2);

In VC7.1, the output is 4, the offset of member2 in struc.

That's a sensible behavior.
I wonder why there is no memory access violation for

That would be another sensible behavior.
"((struc*)0)->member2" ?
And why the output is the offset of struc?

what's the output in pure C compiler? I have no C compiler at hand now.

The code is illegal and it is undefined behavior. That means the system
could do anything. Don't dereference a null pointer. On my system,
running this program automatically closes my web browser and opens my
word processor. Since I have very limited amount of RAM, this took
approximately 2 hours.



Jonathan
 
M

Mark P

Jonathan said:
That's a sensible behavior.




That would be another sensible behavior.




The code is illegal and it is undefined behavior. That means the system
could do anything. Don't dereference a null pointer. On my system,
running this program automatically closes my web browser and opens my
word processor.

Me too! Except on mine it also composes and posts this reply. In fact,
I'm not even aware that I just posted this.
 
S

Scott McPhillips [MVP]

aling said:
Have following code snip:

struct struc {
int member1;
int member2;
} ;
printf("&((struc*)0)->member2=%p\n", &((struc*)0)->member2);

In VC7.1, the output is 4, the offset of member2 in struc.

I wonder why there is no memory access violation for
"((struc*)0)->member2" ?
And why the output is the offset of struc?

There is no memory access violation because there is no memory access.
You have simply asked the compiler to compute the address of the member,
not to read the member. The expression is composed entirely of
constants and the result is computed at compile time.

The output is address 4 because that is the offset from the address of 0
that you supplied.
 
A

aling

Why the result of &((struc*)0)->member2 is a offset instead of address?

Why the two results of following code is different, and one is memory
address, the other is offset?

struct struc {
int member1;
int member2;
} astruc, * p_struc=&astruc, *p_null=0;
printf("&p_struc->member2=%p\n", &p_struc->member2); // this result is
a memory address
printf("&p_null->member2=%p\n", &p_null->member2); // this result is
offset of member2
 
A

aling

Now I understand. The result of &((struc*)0)->member2 is not offset, it
is a memory address, though it can be used as one offset.
 
J

John Harrison

aling said:
Now I understand. The result of &((struc*)0)->member2 is not offset, it
is a memory address, though it can be used as one offset.

The code is not legal, despite the fact that it works. If you need to do
this sort of thing you should use the offsetof macro defined in
<stdlib.h>. Most likely the offsetof macro will do exactly what you are
doing above, but the offsetof macro is guaranteed to work (on C style
structs).

john
 
G

Greg

aling said:
Why the result of &((struc*)0)->member2 is a offset instead of address?

Why the two results of following code is different, and one is memory
address, the other is offset?

struct struc {
int member1;
int member2;
} astruc, * p_struc=&astruc, *p_null=0;
printf("&p_struc->member2=%p\n", &p_struc->member2); // this result is
a memory address
printf("&p_null->member2=%p\n", &p_null->member2); // this result is
offset of member2

The program is calculating the address of the member as if the object
itself were located at memory address 0. So addresses are identical to
offsets since they are both being measured from the same reference
point. Note that the memory address 0 as used in this program is not
necessarily the address that the NULL pointer references. And it is
even conceivable that memory address 0 could be a valid memory location
on a system somewhere. For that reason, the null pointer "0" is, in
C++, a symbolic representation of an invalid object address. The actual
null pointer address used when the code is compiled can be different
and would depend on the implementation.

And as alarming as this program appears, it is nonetheless performing
only pure computation and does not access these hypothetical memory
addresses; so despite appearances, it remains a valid program. Of
course, it's probably still not a good idea to work with pointers in
this way since it is all to easy to make a mistake.

Greg
 
G

Greg Comeau

Now I understand. The result of &((struc*)0)->member2 is not offset, it
is a memory address, though it can be used as one offset.

Right, because structs have subobjects, and so -> effectively moves
to the subobject that is in the position where the respective memory
of the right type starts. IOWs, where that object's offsetof() is.
But, as mentioned, since there really is no such object at 0,
the code is undefined. Better to use offsetof() (although oddly
you may find it using the same implementation, but then at least
you'll know it works, and you'll be using offsetof() anyway
which will be portable so that if you use offsetof on an
implmentation where the undefined behavior is not doing the
obvious things, the vendor will provide for you the right definition
for that platform).
 
G

Greg Comeau

The program is calculating the address of the member as if the object
itself were located at memory address 0. So addresses are identical to
offsets since they are both being measured from the same reference
point. Note that the memory address 0 as used in this program is not
necessarily the address that the NULL pointer references. And it is
even conceivable that memory address 0 could be a valid memory location
on a system somewhere. For that reason, the null pointer "0" is, in
C++, a symbolic representation of an invalid object address. The actual
null pointer address used when the code is compiled can be different
and would depend on the implementation.

This I believe is all correct.
And as alarming as this program appears, it is nonetheless performing
only pure computation and does not access these hypothetical memory
addresses; so despite appearances, it remains a valid program. Of
course, it's probably still not a good idea to work with pointers in
this way since it is all to easy to make a mistake.

The problem though as I recall it is that _the struct_ is not
at address 0. I know both the C and C++ committee looked at this
and recall that it remained undefined behavior. Am I not recalling
a change that was made upon looking at it?
 
P

Pete Becker

Greg said:
Better to use offsetof() (although oddly
you may find it using the same implementation, but then at least
you'll know it works

Indeed. It's not odd, because offsetof is in the standard library. The
standard library is part of the implementation, and the only requirement
is that its components do what they're supposed to do. They can, and
often do, rely on "undefined behavior" which sometimes is quite well
defined for a particular compiler.
 
G

Greg Comeau

Indeed. It's not odd, because offsetof is in the standard library. The
standard library is part of the implementation, and the only requirement
is that its components do what they're supposed to do. They can, and
often do, rely on "undefined behavior" which sometimes is quite well
defined for a particular compiler.

I was trying to say that a newbie may find it odd that a header
file can do something but that they are not necessarily supposed
to do it that same way, and it's worth emphasizing what you say again:
what you sometimes see in headers is for implementors so newbies
before using something that "looks cool" look it up or pass it by this NG.
 

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

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top