Sorry, we seem to be out of sync. By absolute pointer I mean an
arbitrary address, not a physical address.
I.e. something like int *p = (int*)0xcafebabe; where the physical
address need not actually be 0xcafebabe?
(snip)
I'm thinking that a malloc implementation must somehow "make up" an
address to allocate, and in that case it seems to me that it's a bit
arbitrary.
I guess my problem in seeing it is I don't see the difference between an
arbitrary pointer and a non-arbitrary one. That is, what's the
difference between these following two statements?
char *buf1 = NULL; /* Should be valid, right? */
char *buf2 = 0xdeadbeef /* Generates an exception, if I follow you. */
If loading NULL, which is defined to zero AFAIK, is allowed, then what
about this?
NULL, which is defined as zero, is a special case. The pointer constant
zero, which need not be the physical address zero, is guaranteed to be
an address which by itself is fully defined, but dereferencing it
causes undefined behaviour. This does not apply to any other absolute
pointer constant. ("Absolute" used in the Tolf meaning, not the Pop
meaning.)
char *buf = NULL;
buf += 0xdeadbeef;
AFAIK the second line causes undefined behaviour by computing the
non-zero absolute pointer value 0xdeadbeef.
For surely, you have to be allowed to add offsets to a pointer like
this?
for(p = buf; *p; p++) {...}
This is different. If buf points to allocated memory and all bytes from
buf up to and including the first zero byte are also in allocated
memory, this is fully defined and safe. The addresses that allocated
memory resides in are always guaranteed to be fully defined. However,
with the exception of zero, no other addresses are. The only way to
legally end up with allocated memory addresses is either to use the
*alloc() functions, or to take the address of a variable or a string
literal (for example char *p="foobar"
.
This code, for example, causes undefined behaviour:
char *p = malloc(100);
if (p != NULL) {
p+200;
}
The reason is that the line "p+200;" computes an absolute address
which does not reside in allocated memory.
Or could it be that they (these platforms) have a concept of an
undefined pointer when storing NULL? In that case, what about this?
char *buf = (char *)malloc(1);
buf += (0xdeadbeef - (int)buf); /* Note incrementation, not storage */
This, I think, also causes undefined behaviour, simply because
computing the address 0xdeadbeef causes undefined behaviour, unless
it happens to be in allocated memory.
I guess I'm just having a hard time understanding how such a platform
would work... would you mind providing an example of such a platform for
me to study? I guess it is at times like these that I really hate the
fact that archs other than i386 are so prohibitively expensive to get my
hands on... :-(
Get a second-hand Amiga, Atari ST or old-fashioned Macintosh. You can get
an MC68000 environment, which is definitely non-i386, for less than
$50.