willey@arrakis.nevada.edu (James P. Willey) (07/23/89)
Recently, I wrote a bubble sort in C for a class I was taking. Sounds easy enough, right? Wrong. The sort worked fine, but my function to read the data in interfered with the execution of the code. I kept getting an error in getchar(), not in my code. I checked with several other syudents and the professor, but nobody could figure it out. I finally realized that the function name "read" was the culprit. Are there other function names to avoid with the cc compiler, or any others for that matter? Thanks. ____ We're happy little worms, We love to squish and squirm, We catch the big ones every time, Because we're hooked on you. Cadillac of worms. We're the Cadillac of worms. We're the Cadillac of worms. We're the Cadillac of worms. So remember, Red Wrigglers, the Cadillac of worms.
gwyn@smoke.BRL.MIL (Doug Gwyn) (07/23/89)
In article <712@unsvax.NEVADA.EDU> willey@arrakis.uucp (James P. Willey) writes: >... I finally realized that the function name "read" was the culprit. >Are there other function names to avoid with the cc compiler, or any >others for that matter? I assume that your problem was that getchar() eventually called read(), expecting the version in the system's C library, but instead found one you had written as part of your program. Standard-conforming C implementations are quite constrained in this regard, and would not have invoked your read() function by mistake. Unfortunately, you have a C implementation that evolved in the "bad old days" before the name-space pollution problem drew the attention that it deserved. Assuming you have a UNIX system, you can obtain a complete list of external symbols referred to by routines in the C library, which is therefore a list of external symbols you need to avoid defining in your programs, by something like the following: nm /lib/libc.a | grep 'U _' | sed 's/.* //' (Details depend on your particular system.) There are also macros in the standard headers that you need to watch out for: cat /usr/include/*.h | grep '^[ ]*#[ ]*define' | sed 's/^[ ]*#[ ]*define[ ]*\([^(]*\).*/\1/' You can also get burned by a few other symbols in system headers, notably typedefs such as "ushort" or "ushort_t", occasionally structure tags and other names. Also avoid using names that start with an underscore; for example the following will break in almost any UNIX C implementation (due to its use of _iob in the definition of getchar): #include <stdio.h> func() { int _iob[10]; _iob[0] = getchar(); } Generally, if you can manage to avoid a name collision using a pre- Standard C implementation, you're entitled to consider it a minor miracle.
kml@ncifcrf.gov (Kevin Lahey) (07/24/89)
In article <10589@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes: >In article <712@unsvax.NEVADA.EDU> willey@arrakis.uucp (James P. Willey) says: >>... I finally realized that the function name "read" was the culprit. > >I assume that your problem was that getchar() eventually called read(), >expecting the version in the system's C library, but instead found one >you had written as part of your program. > >Standard-conforming C implementations are quite constrained in this >regard, and would not have invoked your read() function by mistake. Yow! Could you elaborate on this? I don't quite understand. Certainly, had he made a declaration: static read () { blah blah } then I could see how to avoid a collision. I just don't quite see how to insure that a regular function declaration doesn't override a library function. Assuming that this magic system works (I don't doubt that it does), how can one override a library function when desired? I made a brief perusal of the second edition of K & R, but I was not enlightened. Could you give me some pointers about where to look? Obviously, I'm not all up on the new ANSI-C stuff, but I want to be. Thanks, Kevin kml@fcs280s.ncifcrf.gov NCI Supercomputer Center, Frederick, Maryland kml@mosquito.cis.ufl.edu UF CIS Department, Gainesville, Florida Whenever you find that you are on the side of the majority, it is time to reform. -- Mark Twain
willey@arrakis.nevada.edu (James P. Willey) (07/24/89)
I don't have the original error producing code anymore, but I tried to reproduce the error. Unfortunately, [or maybe fortunately] I was unable to reproduce the error. [I have since been moved to a new machine.] It was run on either 4.2 BSD or 4.3 BSD UNIX. The code was something like this: #include <stdio.h> #include <ctype.h> int c,f; main() { f = read(); } int read() { int index = 0; while (c == '\t' || c == ' ') c = getchar(); while (isdigit(c)) { index = index * 10 + c - '0'; c = getchar(); } return(index); } The error came in filbuf at 0x116 [from memory, so I'm not quite sure where in filbuf]. No matter where in the code getchar() was called from, the same error occurred. I wish I had saved the original code, but at the time I didn't see any reason to save code from hell :-) Thanks for the help!!!
gwyn@smoke.BRL.MIL (Doug Gwyn) (07/24/89)
In article <1185@fcs280s.ncifcrf.gov> kml@ncifcrf.gov (Kevin Lahey) writes: >I just don't quite see how to insure that a regular function declaration >doesn't override a library function. Assuming that this magic system works >(I don't doubt that it does), how can one override a library function when >desired? A standard-conforming implementation is not allowed to call functions other than those specified as being in the standard library and others (primarily with names beginning with underscore) that are specifically reserved for the implementation by the Standard. read() is an example of a function that a conforming C implementation must permit applications to use for their own purposes. A strictly conforming program is not allowed to provide its own version of any of the standard library functions. Primarily this is because such a substitution may well break the implementation, especially when there are internal implementation constraints of which the application programmer is unaware. (It does happen.) read(), however, is not a standard C library function, although in an IEEE 1003.1 environment read() is assumed to be available from the library. Implementations that are simultaneously ANSI C and IEEE 1003.1 conforming will provide read() in their C library, but will invoke a different name such as _read() from within their stdio functions or use some other similar scheme to avoid calling a user-provided read() function. If you were designing a language from scratch, there would be much better means available to avoid name collision. Ada "packages" are an example of such a mechanism. However, we're stuck with C as it has historically evolved, and the proposed Standard has gone about as far as feasible in this direction.
spl@mcnc.org (Steve Lamont) (07/24/89)
In article <10594@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes: >In article <1185@fcs280s.ncifcrf.gov> kml@ncifcrf.gov (Kevin Lahey) writes: >>I just don't quite see how to insure that a regular function declaration >>doesn't override a library function. Assuming that this magic system works >>(I don't doubt that it does), how can one override a library function when >>desired? > >A standard-conforming implementation is not allowed to call functions >other than those specified as being in the standard library and others >(primarily with names beginning with underscore) that are specifically >reserved for the implementation by the Standard. read() is an example >of a function that a conforming C implementation must permit applications >to use for their own purposes. Based upon this information, I have a couple of questions. Suppose that I wish to implement my own math library function, say sin() or cos(), for whatever reason, in a large pre-existing piece of code that I don't want to fiddle too much with. How would I do this, then? Also, what provision is there for overriding this stricture, if, for instance, I am assigned the task of rebuilding a standard library? Is the compiler going to refuse to let me write my own read() function then, too? -- spl Steve Lamont, sciViGuy EMail: spl@ncsc.org North Carolina Supercomputing Center Phone: (919) 248-1120 Box 12732/RTP, NC 27709
gwyn@smoke.BRL.MIL (Doug Gwyn) (07/25/89)
In article <4935@alvin.mcnc.org> spl@mcnc.org.UUCP (Steve Lamont) writes: >Suppose that I wish to implement my own math library function, say sin() or >cos(), for whatever reason, in a large pre-existing piece of code that I don't >want to fiddle too much with. How would I do this, then? Since it is unlikely that any non-math function in the C library would invoke cos() or sin(), you might be able to get away with simply providing your own, but it is not guaranteed to be portable to do so. Much better would be for you to name your functions my_cos() and my_sin(), and include something like the following in your application header file: #undef cos /* in case <math.h> uses a #define cos $$COS etc. */ #define cos my_cos #undef sin #define sin my_sin Then include your application header file AFTER <math.h> in your sources. >Also, what provision is there for overriding this stricture, if, for instance, >I am assigned the task of rebuilding a standard library? Is the compiler >going to refuse to let me write my own read() function then, too? It all depends on the implementation. The (conforming) compiler is never going to refuse to allow you to write a read() function; it may refuse to allow you to write a __read() function, however, since that's in the implementation's reserved name space. In practice I don't expect compilers to be so constraining, because probably the same compiler is used to build the C library as is used for application programs.
gwyn@smoke.BRL.MIL (Doug Gwyn) (07/25/89)
In article <10599@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes: > #undef sin > #define sin my_sin Also: extern double my_sin(double);
ari@eleazar.dartmouth.edu (Ari Halberstadt) (07/25/89)
In article <10599@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes: >In article <4935@alvin.mcnc.org> spl@mcnc.org.UUCP (Steve Lamont) writes: >>Suppose that I wish to implement my own math library function, say sin() or >>cos(), for whatever reason, in a large pre-existing piece of code that I don't >>want to fiddle too much with. How would I do this, then? >Much better would be for you to name your functions my_cos() and my_sin(), >and include something like the following in your application header file: > #undef cos /* in case <math.h> uses a #define cos $$COS etc. */ > #define cos my_cos > #undef sin > #define sin my_sin I must voice a small criticism of the above scheme. By redefining a standard function name, you may be greatly confusing any programmers who try to read your code. These programmers will expect any standard named function to be IDENTICAL to the standard library function. Unless you've completely debugged and tested it for compatability, they won't know what hit them. Also, what if someone copies your code without including the header file, since they assumed it was not needed. Then, when they try to run it, it won't perform! I think there was another reason, but I can't remember it right now. At any rate, I always opt for calling functions either "my_sin()", or "xsin()". I use the second when I'm sick of seeing "my" all over the place (for instance, on the Macintosh I replaced the standard file package with my own mini-package, and prefixed all the standard names with "x", to get "xfopen()", xgetc() "XFILE *", "xstdio.h", etc.) On UNIX you can use the tools "ed" or "sed" (or awk if you want to be fancy...) to change all the original function calls. -- Ari Halberstadt '91, "Long live succinct signatures" E-mail: ari@eleazar.dartmouth.edu Telephone: (603)640-5687 Mailing address: HB1128, Dartmouth College, Hanover NH 03755
seanf@sco.COM (Sean Fagan) (07/27/89)
In article <10589@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes: >Standard-conforming C implementations are quite constrained in this >regard, and would not have invoked your read() function by mistake. The only current standard for C makes no mention of that. That standard, of course, is K&R. The dpANS requires that users be able to do that; however, it is not yet a standard! -- Sean Eric Fagan | "Uhm, excuse me..." seanf@sco.UUCP | -- James T. Kirk (William Shatner), ST V: TFF (408) 458-1422 | Any opinions expressed are my own, not my employers'.
dave@micropen (David F. Carlson) (07/27/89)
In article <1185@fcs280s.ncifcrf.gov>, kml@ncifcrf.gov (Kevin Lahey) writes: ] In article <10589@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes: ] >In article <712@unsvax.NEVADA.EDU> willey@arrakis.uucp (James P. Willey) says: ] >>... I finally realized that the function name "read" was the culprit. ] > ] >I assume that your problem was that getchar() eventually called read(), ] >expecting the version in the system's C library, but instead found one ] >you had written as part of your program. ] > ] ] then I could see how to avoid a collision. I just don't quite see ] how to insure that a regular function declaration doesn't override ] a library function. Assuming that this magic system works (I don't ] doubt that it does), how can one override a library function when desired? ] ] I made a brief perusal of the second edition of K & R, but I was ] not enlightened. Could you give me some pointers about where to look? ] Obviously, I'm not all up on the new ANSI-C stuff, but I want to be. One way available under sysV is to use the -M flag for ld(1). The loader will barf loudly if a duplicate extern reference occurs. This is not a language "problem" as much as it is a link-loader problem. C does allow implicit referencing and seperate compilation. (A programmer once named a function kill(). *Very* ugly things happened.) -- David F. Carlson, Micropen, Inc. micropen!dave@ee.rochester.edu "The faster I go, the behinder I get." --Lewis Carroll
ggg@sunquest.UUCP (Guy Greenwald) (07/28/89)
In article <4935@alvin.mcnc.org>, spl@mcnc.org (Steve Lamont) writes: > Suppose that I wish to implement my own math library function, say sin() or > cos(), for whatever reason, in a large pre-existing piece of code that I don't > want to fiddle too much with. How would I do this, then? Declare the routine name before it is invoked, then define the routine to be static. Here's an example: main() { /* Declare the function here */ double sin(); double x, something; /* ... code ... */ x = sin(something); } static double sin(angle) double angle; { double value; /* Steve's slick sine calculation */ return value; } It is the combination of the static definition and the declaration before use that avoids the problem with the duplicate name in the run-time library.
robert@arizona.edu (Robert J. Drabek) (07/28/89)
In article <175@sunquest.UUCP>, ggg@sunquest.UUCP (Guy Greenwald) writes: > In article <4935@alvin.mcnc.org>, spl@mcnc.org (Steve Lamont) writes: > > Suppose that I wish to implement my own math library function, say sin() > > Declare the routine name before it is invoked, then define the routine to be > static. Here's an example: > > main() > { > double sin(); > x = sin(something); > } > > static double sin(angle) > double angle; > { > /* Steve's slick sine calculation */ > } > > It is the combination of the static definition and the declaration before use > that avoids the problem with the duplicate name in the run-time library. Sigh. First, Guy specifies (by default) external linkage for the function and then later declares it to be static. A good compiler should complain about this disparity in storage classes. Simply placing "static" at the beginning of the first declaration could solve that. BUT since the original poster talked about large existing code, we would want to be careful about the possibility of <math.h> already being included. So, we still haven't solved it. Most importantly, though, is what happens during linking? Try it in various environments and you will find that sometimes it links with the library sin() [VMS] and sometimes with your own [Unix cc]. The linker probably doesn't care about your declarations. (Try Ada if you really want that.) Name space problems have been around since before computers, and we simply carried them along to this new domain. What is wrong with creating a name for your new sine function which has a lower probability of conflict (letting you get on to more interesting topics) when you don't want to replace the library function? If you really want to replace calls to such "standard" functions with calls to your own, I don't think you will find a universal method using the compiler and linker proper. The preprocessor, though, could be used with something like maybe #define sin(x) my_sin(x) -- Robert J. Drabek Department of Computer Science The University of Arizona Tucson, AZ 85721
ggg@sunquest.UUCP (Guy Greenwald) (07/28/89)
In article <12911@megaron.arizona.edu>, robert@arizona.edu (Robert J. Drabek) writes: > Sigh. > > First, Guy specifies (by default) external linkage for the function and > then later declares it to be static. A good compiler should complain > about this disparity in storage classes. Simply placing "static" at the > beginning of the first declaration could solve that. > > BUT since the original poster talked about large existing code, we would > want to be careful about the possibility of <math.h> already being > included. So, we still haven't solved it. > > Most importantly, though, is what happens during linking? Try it in > various environments and you will find that sometimes it links with the > library sin() [VMS] and sometimes with your own [Unix cc]. The linker > probably doesn't care about your declarations. (Try Ada if you really > want that.) > > Name space problems have been around since before computers, and we > simply carried them along to this new domain. > > What is wrong with creating a name for your new sine function which has > a lower probability of conflict (letting you get on to more interesting > topics) when you don't want to replace the library function? If you > really want to replace calls to such "standard" functions with calls to > your own, I don't think you will find a universal method using the > compiler and linker proper. The preprocessor, though, could be used > with something like maybe > #define sin(x) my_sin(x) Robert and I worked together once. We spent a lot of our time arguing, but eventually it got too personal for me. I just can't resist answering this time, but as Robert points out, there are more interesting topics than this one. He'll have the last word. I agree with your first point. A static declaration would be more consistent. However, neither the UNIX C compiler on our Sun nor the VMS C compiler on our MicroVAX complained. There was not a peep from lint, either. You claim that if math.h is included, the problem isn't solved. I tested the following piece of code on both systems mentioned above: #include <stdio.h> #include <math.h> main() { double sin(); (void) printf("%f\n", sin(.7)); } static double sin(angle) double angle; { return angle; } In both cases, the value 0.700000 was printed. Did I miss something here? It sure seemed like the linker did what I thought it would. Perhaps you have a piece of code that proves the VMS linker chooses the RTL and the UNIX linker doesn't. What did I miss? As to your last two points, I agree. Better to avoid the problem in the first place by selecting names more carefully. I also like the #define. Thanks for the ideas.
gwyn@smoke.BRL.MIL (Doug Gwyn) (07/29/89)
In article <3100@scolex.sco.COM> seanf@scolex.UUCP (Sean Fagan) writes: -In article <10589@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes: ->Standard-conforming C implementations are quite constrained in this ->regard, and would not have invoked your read() function by mistake. -The only current standard for C makes no mention of that. That standard, of -course, is K&R. If K&R first edition is to be accepted as a standard, then why not K&R second edition? I think you're just being silly. Everyone knew the context of the discussion.
seanf@sco.COM (Sean Fagan) (07/30/89)
In article <10620@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes: >If K&R first edition is to be accepted as a standard, then why not K&R >second edition? I think you're just being silly. Everyone knew the >context of the discussion. Yes, I was being somewhat silly. However, your response, at a time when there is not a *single* ANSI-compliant C compiler (partially because there *is* not an ANSI C standard) was on the order of "Well, you can't do that, nyah nyah nyah." I've been seeing too much of that, and it's really not a useful response. Then again, this probably isn't, either 8-). C related notice: has anybody but myself noticed that the current dpANS does not seem to require that the implementation-dependent (or defined) options can change between modules? Provided everything works, there is no reason why, for example, sizeof(int) in one module could be 2, and 4 in another (again, provided everything works properly with the libraries...). -- Sean Eric Fagan | "Uhm, excuse me..." seanf@sco.UUCP | -- James T. Kirk (William Shatner), ST V: TFF (408) 458-1422 | Any opinions expressed are my own, not my employers'.
gwyn@smoke.BRL.MIL (Doug Gwyn) (07/31/89)
In article <3109@scolex.sco.COM> seanf@scolex.UUCP (Sean Fagan) writes: >However, your response, at a time when there is not a *single* >ANSI-compliant C compiler (partially because there *is* not an ANSI >C standard) was on the order of "Well, you can't do that, nyah nyah nyah." The question was about name space pollution. I explained that such problems are addressed by the proposed C Standard, in addition to explaining how to determine what names to avoid in writing programs in a pre-Standard C environment. Even though ANSI has not yet ratified the proposed Standard, it is technically stable, and there have been several compilers claiming conformance or "compatibility" with the Standard. I have them on my Apple IIGS and one of the BRL Crays. I've seen them advertised for IBM PCs. Thus Standard conformance is a practical matter, not just an academic one. The "nyah, nyah, nyah" is solely in your own mind. I just answered the question, the only editorial comment being that it was unfortunate that the name space pollution issue hadn't been adequately addressed before the C Standard, an assessment I will stand by. >C related notice: has anybody but myself noticed that the current dpANS >does not seem to require that the implementation-dependent (or defined) >options can change between modules? Provided everything works, ... So long as the implementor is able to specify the required information, indeed arbitrarily complex rules could be adopted. As you say, the Standard specifications must be met. That does constrain the extent to which the implementation can vary its behavior from case to case.
karl@haddock.ima.isc.com (Karl Heuer) (08/03/89)
In article <10633@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes: >In article <3109@scolex.sco.COM> seanf@scolex.UUCP (Sean Fagan) writes: >>C related notice: has anybody but myself noticed that the current dpANS >>does not seem to require that the implementation-dependent (or defined) >>options can change between modules? Provided everything works, ... > >So long as the implementor is able to specify the required information, >indeed arbitrarily complex rules could be adopted. Here's an example where such flexibility is useful: it allows the "implementation-defined" equivalent-type of a enum to be "the narrowest integral type that's capable of containing all values of the enumeration constants". Thus on such an implementation, enum {RED,BLUE,GREEN} would be stored in a char-sized object, while still allowing for the existence of large-range enums, which would be stored in a full word. Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint