wggabb@sdrc.COM (Rob Gabbard) (06/11/91)
A call to strcat with NULL as the second argument core dumps with a memory fault on Ultrix. Why would anyone want to do this anyway ? How about.... strcat(foo,getenv("FOO")) instead of if (getenv("FOO")) strcat(foo,getenv("FOO")); Actually, just coding strcat(foo,NULL) will dump. Anyone run into this ? Am I doing a no-no here. -- The statements above are my own and do not neccesarily reflect the opinion of my employer. ------------------------------------------------------------------------------- Rob Gabbard wggabb@sdrc.sdrc.com Technical Development Engineer Structural Dynamics Research Corporation
lwm@bronze.ucs.indiana.edu (Larry Meehan) (06/12/91)
In <966@sdrc.COM> wggabb@sdrc.COM (Rob Gabbard) writes: >A call to strcat with NULL as the second argument core dumps with a memory >fault on Ultrix. ... >Actually, just coding strcat(foo,NULL) will dump. Anyone run into this ? >Am I doing a no-no here. You must be on one of the MIPS-based DEC systems. Due to a quirk of the VAX port of ULTRIX, you can get by with what you are trying to do, but you are, strictly speaking, doing a no-no. The thing to remember is that NULL is not the same thing as "", since strcat(foo,"") will work just fine. This program will fail too for *exactly* the same reason: main() { char *p, c; p = (char *) 0; c = *p; } If you look in /usr/include/stdio.h, you will see that NULL is really just 0, so our programs are trying to access location 0 which is legal on a VAX, but not on the MIPS implementation of Ultrix. A lot of "bug-free" code broke when it was moved from VAX to non-VAX systems. The little program above dumps core on a MIPS CPU and runs without errors on a VAX. The program is at fault, not Ultrix. Hope this helps. -- Larry Meehan University Computing Services lwm@ucs.indiana.edu Indiana University ("Industry without art is brutality." -- Ananda Coomaraswamy) -- Larry Meehan University Computing Services lwm@ucs.indiana.edu Indiana University ("Industry without art is brutality." -- Ananda Coomaraswamy)
diamond@jit533.swstokyo.dec.com (Norman Diamond) (06/12/91)
In article <966@sdrc.COM> wggabb@sdrc.COM (Rob Gabbard) writes: >A call to strcat with NULL as the second argument core dumps with a memory >fault on Ultrix. Why would anyone want to do this anyway ? How about.... > strcat(foo,getenv("FOO")) > instead of > if (getenv("FOO")) strcat(foo,getenv("FOO")); The behavior is undefined according to the C standard. Core dumps are a common result (although they used to be less common when one particular hardware architecture used to be more common). If you want to change the C language (including the standard library), wait for the ANSI committee to begin preparing the next revision of the language, and make your suggestions to them. It probably won't be a long wait; proceedings for the 1989 standard began around 8 years ago. They have probably heard this one before, so you will probably have to get a lot of people on your side to join the committee and vote for your proposal. >Actually, just coding strcat(foo,NULL) will dump. Anyone run into this ? Yes. Mostly new programmers, and also some irresponsible (i.e. experienced enough to know better, but lazy -- they know who they are) ones. >Am I doing a no-no here. Yes. -- Norman Diamond diamond@tkov50.enet.dec.com If this were the company's opinion, I wouldn't be allowed to post it. Permission is granted to feel this signature, but not to look at it.
grr@cbmvax.commodore.com (George Robbins) (06/12/91)
In article <966@sdrc.COM> wggabb@sdrc.COM (Rob Gabbard) writes: > A call to strcat with NULL as the second argument core dumps with a memory > fault on Ultrix. Why would anyone want to do this anyway ? How about.... > > Actually, just coding strcat(foo,NULL) will dump. Anyone run into this ? > Am I doing a no-no here. You is doing a no-no. NULL is not a defined to be a usable pointer value, it is only a flag that no meaningful value is being provided for the argument. Of course, with many compilers, NULL is kinda equivalent to "" (a null string), but this isn't guaranteed. -- George Robbins - now working for, uucp: {uunet|pyramid|rutgers}!cbmvax!grr but no way officially representing: domain: grr@cbmvax.commodore.com Commodore, Engineering Department phone: 215-431-9349 (only by moonlite)
diamond@jit533.swstokyo.dec.com (Norman Diamond) (06/12/91)
In article <1991Jun12.040043.24091@bronze.ucs.indiana.edu> lwm@bronze.ucs.indiana.edu (Larry Meehan) writes: [First an explanation of why dereferencing NULL is illegal, which was correct, but had not yet arrived at this site when I previously replied. But then...] >If you look in /usr/include/stdio.h, you will see that NULL is really just 0, >so our programs are trying to access location 0 Sorry, but you can't see that from looking in /usr/include/stdio.h. When a source program uses an integer constant 0 as a pointer, the compiler must recognize it as a null pointer constant. However, a null pointer constant does not have to be address 0 at execution time. If the source program uses 0 for an integer, its binary value has to consist of 0-bits, but for a null pointer it does not have to do so. For example, in some implementations, a byte of storage might be allocated somewhere and never used for anything legal, but the implementation will use its address as a null pointer. For another example, on some Intel processors, it would be very nice to use address (some segment):FFFF as a null pointer, so that the hardware would trap some illegal dereferences. In these cases, a 0 in the source program, compiled to a null pointer constant, accesses a location other than 0. These topics come up frequently in newsgroups comp.lang.c and comp.std.c. The C programming language is confusing in this and in other ways. It was not designed for friendliness to mortals. >which is legal on a VAX, No. (Personal opinion, not the company's opinion.) It was uncaught (usually) and benign (usually), but illegal since day 1, even before K&R-1. >but not on the MIPS implementation of Ultrix. Not anywhere. Well, hypothetically an implementation could define an extension to the language, and the program would be legal on such an implementation, but I don't think any real implementation specifies this. -- Norman Diamond diamond@tkov50.enet.dec.com If this were the company's opinion, I wouldn't be allowed to post it. Permission is granted to feel this signature, but not to look at it.
ltf@ncmicro.lonestar.org (Lance Franklin) (06/13/91)
In article <966@sdrc.COM> wggabb@sdrc.COM (Rob Gabbard) writes: }A call to strcat with NULL as the second argument core dumps with a memory }fault on Ultrix. Why would anyone want to do this anyway ? How about.... } } strcat(foo,getenv("FOO")) } } instead of } } if (getenv("FOO")) strcat(foo,getenv("FOO")); Try: if ((s=getenv("FOO"))) strcat(foo,s); Where s is defined as (char *). } }Actually, just coding strcat(foo,NULL) will dump. Anyone run into this ? }Am I doing a no-no here. Yup...figure it out, why put up with a lot of overhead on error checking on string handling routines where 95% of the calls are of the type: strcat(foo,"string"); After all, if you check for NULL on strcat, you might as well do it in all the other str* routines...that's a lot of error checking in a set of routines you would prefer to be as fast as possible. Lance -- Lance T. Franklin +----------------------------------------------+ (ltf@ncmicro.lonestar.org) | "You want I should bop you with this here | NC Microproducts, Inc. | Lollipop?!?" The Fat Fury | Richardson, Texas +----------------------------------------------+
lwm@bronze.ucs.indiana.edu (Larry Meehan) (06/13/91)
In article <1991Jun12.040043.24091@bronze.ucs.indiana.edu> lwm@bronze.ucs.indiana.edu (Larry Meehan) writes: >which is legal on a VAX, What I meant was that it results in a legal memory reference. In <1991Jun12.062045.13467@tkou02.enet.dec.com> diamond@jit533.swstokyo.dec.com (Norman Diamond) writes: >When a source program uses an integer constant 0 as a pointer, the compiler >must recognize it as a null pointer constant. However, a null pointer >constant does not have to be address 0 at execution time. If the source >program uses 0 for an integer, its binary value has to consist of 0-bits, >but for a null pointer it does not have to do so. I always knew that NULL could have a non-zero value, depending on implementation details, but I didn't realize it could be specified as 0 in the source and that the compiler would translate this to the "correct" value. I have always tried to avoid writing code that assumes anything about the value of NULL. I have always felt uneasy about constructs like while (*argv) and avoided them myself. It sounds from what you say like this is a very dangerous (non-portable) line of code. I mean, is the compiler expected to translate this to while (*argv != NULL) on systems that have a non-zero value for NULL? I realize this newsgroup is not about C programming, but this issue will probably continue to bite DEC customers who move from VAX to RISC, so it is probably good for it to appear here once in a while. -- Larry Meehan University Computing Services lwm@ucs.indiana.edu Indiana University ("Industry without art is brutality." -- Ananda Coomaraswamy) -- Larry Meehan University Computing Services lwm@ucs.indiana.edu Indiana University ("Industry without art is brutality." -- Ananda Coomaraswamy)
diamond@jit533.swstokyo.dec.com (Norman Diamond) (06/13/91)
In article <1991Jun12.214124.24990@bronze.ucs.indiana.edu> lwm@bronze.ucs.indiana.edu (Larry Meehan) writes: >In <1991Jun12.062045.13467@tkou02.enet.dec.com> diamond@jit533.swstokyo.dec.com (Norman Diamond) writes: >>When a source program uses an integer constant 0 as a pointer, the compiler >>must recognize it as a null pointer constant. However, a null pointer >>constant does not have to be address 0 at execution time. If the source >>program uses 0 for an integer, its binary value has to consist of 0-bits, >>but for a null pointer it does not have to do so. >I have always tried to avoid writing code that assumes anything about the >value of NULL. I have always felt uneasy about constructs like > while (*argv) >and avoided them myself. It sounds from what you say like this is a very >dangerous (non-portable) line of code. No. This is perfectly portable and not dangerous. >I mean, is the compiler expected to translate this to > while (*argv != NULL) >on systems that have a non-zero value for NULL? while (*argv) while (*argv != 0) while (*argv != (void *) 0) while (*argv != NULL) while (*argv != (char *) 0) /* only because *argv has type (char *) */ are all equivalent. The compiler is required to translate all of these to compare *argv to run-time representation of a null pointer if equal, jump out of the loop [contents of loop] jump back to the compare The run-time representation might or might not be binary zeroes. If the source code has integer constant 0, (void *) 0, or NULL, (or, as in while (*argv), an implied occurrence of one of these), in a place where it must be a pointer, then the compiler is required to translate it to the run-time representation of a null pointer. However, for example, while ((int) *argv != 0) /* casting pointer to int, and comparing ints */ while ((unsigned long) *argv != 0) /* approximately the same */ are unportable and dangerous. >I realize this newsgroup is not about C programming, but this issue will >probably continue to bite DEC customers who move from VAX to RISC, so it >is probably good for it to appear here once in a while. It will bite anyone who wrote code for an implementation represents null pointers by all 0-bits (too many, IMHO, because all 1-bits would be easy to trap on many Intel processors), or more accurately where fetching from the location addressed by a null pointer does not trap, and then moves to an implementation where it does trap. I once read that some vendor had changed their kernel to waste a page of (virtual and real) storage for every process, because that was easier than fixing applications that came from a certain irresponsible organization that should have known better. Follow-ups are directed to comp.lang.c because it really is a language issue. (Readers of comp.std.c probably don't want to be bothered by it again.) -- Norman Diamond diamond@tkov50.enet.dec.com If this were the company's opinion, I wouldn't be allowed to post it. Permission is granted to feel this signature, but not to look at it.