Path: utzoo!attcan!uunet!aplcen!haven!adm!smoke!gwyn From: gwyn@smoke.BRL.MIL (Doug Gwyn) Newsgroups: comp.unix.wizards Subject: Re: What machines core dump on deref of NULL? Message-ID: <13316@smoke.BRL.MIL> Date: 8 Jul 90 05:49:48 GMT References: <13226@smoke.BRL.MIL> <1990Jun29.132304.12550@athena.mit.edu> <418@minya.UUCP> Organization: U.S. Army Ballistic Research Laboratory, APG, MD. Lines: 77 In article <418@minya.UUCP> jc@minya.UUCP (John Chambers) writes: >In article <1990Jun29.132304.12550@athena.mit.edu>, jik@athena.mit.edu (Jonathan I. Kamens) writes: >> From K&R Second Edition, Page 102: "C guarantees that zero is never a >> valid address for data, so a return value of zero can be used to signal >> an abnormal event, in this case, no space." Note that that's in the tutorial section of the book, where rigor is sometimes compromised in order to avoid overwhelming the reader with too much technical detail. A fully rigorous formulation of the rule would have hurt more than it would have helped. >And on page 192 of my C bible I find the paragraph: > The compilers currently allow a pointer to be assigned to an integer, > an integer to a pointer, and a pointer to a pointer of another type. > The assignment is a pure copy operation, with no conversion. This > usage is nonportable, and may produce pointers which cause address > exceptions when used. However, it is guaranteed that assignment of > the constant 0 to a pointer will produce a null pointer distinguish- > able from a pointer to any object. Note that this was removed for the Second Edition; in the intervening years the semantics of null pointers and pointer conversion were worked out more thoroughly. The current rule is that the operation IS a conversion and in some cases an explict cast is required; also, while a constant expression that LOOKS like the conversion of the integer value 0 to a pointer is used in source code to represent a null pointer constant, this particular usage is a special case that may have to be specially recognized by the compiler in some environments. >The trouble with this statement is that I've never seen a C compiler >that implements it. On extant processors, it is simple to prove that >it can't be implemented. If you examine any of the current commercial >processors (68xxx, 8xx86, SPARC, MIPS, PDP11/VAX, etc.), you quickly >learn that all of them have the property that there is no bit pattern >that is guaranteed to cause a fault when used as an address. Nowhere is it stated or implied that a fault must occur when a pointer is improperly used! In fact, some implementations DO fault when a null pointer is dereferenced; this is allowed but not required. It is also not required that the HARDWARE reserve a particular address bit pattern for use as a null pointer. On good old PDP-11 UNIX, the all-zero bit pattern was used for this purpose by the C implementation, which also made sure that no officially-defined C object existed at the location with address zero. That's more or less what the old citation you gave was trying to say about that use of zero. However, that is NOT a requirement on C implementations these days. In particular, one could choose to use the address of a reserved C run-time library object whose external name is, for example, __NULL as the implementation's null pointer value. (The compiler is then obliged to translate source-code constructs such as (foo*)0 to references to &__NULL.) >On such processors, C simply can't be implemented in conformance with >such standards, no matter how much we'd like it. Sure it can. We made quite sure of that when drafting the standard. >BTW, perhaps this should be asked in comp.lang.c (though I recall it >being discussed a few years back, with much flamage but few answers); >can anyone show how one would portably code a statement that assigns >the value zero (not null) to a pointer? The flamage occurs because certain people simply refuse to listen to the correct modern rules concerning null pointers in C. Here is an example of how you can access location 0 regardless of the way that null pointers happen to be implemented: thing *p; p = (thing*)sizeof(thing); --p; *p; This is of course nonportable, but then any assumption about actual assignment of address values is necessarily nonportable. However, it should work for the kind of flat address space environment that you've been postulating.