Many programs under Unix at least unknowingly use the fact that using a
zero pointer as a "char *" will give you a null string. Although these
are many times bugs which nobody has yet found, we have found in bringing
up Phoenix under VMS that a large number of programs will break if
there is not a null string at 0. The way this works on a VAX is that
the entry point for crt0 contains a register save mask which specifies that
no registers be saved. Since crt0 gets loaded at address 0, this results
in a zero word at address zero, and thus, a null string at 0. In answer
to your question:
What if I do "int *a = 0, *b = 0; *b = 10; i = *a;"? What is
the value of i? Does this mean that assigning indirect through
a nil pointer is deadly to the rest of your nil pointer derefs?
the result would be a Bus Error, since location zero is part of the
text, rather than the data, and is thus write protected (except, of
course, under the OMAGIC format where the result in "i" would be
10). I have not found any programs that try to write at address 0,
but there certainly are those that rely on reading there.
Dave Johnson
Rice University
Actually, in Vax virtual memory you always have something at 0;
you have the stuff that is in /lib/crt0.o (or /lib/mcrt0.o if you
compiled with -p) but it isn't necessarily zero. However, you
should never trust to *(int *)0 being legal -- it's not on a large
number of machines (e.g. Codatas). This seems to be a common
"berkeleyism" (assuming that *(int *)0 is legal). If you have
a pointer which could be nil, then you should always check it
first, before following it.
if (p == (int *) 0 || *p == 0) {
some code...
}
or something like that.
Dave Martindale
Guy Harris
RLG Corporation
{seismo,mcnc,we13}!rlgvax!guy
For programs made with "cc" (without running "ld" explicitly), Berkeley
4.1BSD DOES (implicitly) guarantee a zero byte at address 0. The fact
that you had problems with this in porting a locally written C program
from Unix 4.1 to VMS/Eunice is a bug in Eunice, not a problem with Unix.
4.1BSD crt0.o ALWAYS has a zero register save mask in it and is ALWAYS
loaded at address 0 by "cc". Crt0 is written in assembler and has an
explicit ".word 0x0000" for a register save mask. In addition, the value
of the register save mask in crt0 has no affect on saving registers,
since the Unix kernel does not "call" the program, but rather jumps
directly into it after the register save mask. Saving the registers is
not necessary since there is nowhere to return to abover crt0. In writing
our Unix emulator Phoenix, I have been very careful of details like this
which cause Unix programs to break. Phoenix will run almost any Unix
program under VMS unmodified, even those that depend on undocumented
details of the Unix environment such as this.
Dave *B* Johnson
Dept. of Mathematical Sciences
Rice University
P.S. Dave *D* Johnson, huh? I like your name...
if (p != NULL && whatever(p))
instead of
if (whatever(p))
or whatever the erroneous code was doing. It's only two instructions on a
VAX.... Several machines (the SUN and the CCI Power/5, both 68000-based, for
example) use the lower part of the address space for the kernel, and
dereferencing null pointers on those systems causes a fault (as it should!).
VMS also maps page 0 out of the address space; I cast my vote either for
demand-paged pure executables (or *all* executables) explicitly starting
the text at 1024 and setting page 0's permissions to no read, no write, no
execute, no way, or adding a new executable type which does this.
Mike Lutz (ucbvax!allegra!rochester!ritcv!mjl)