[comp.lang.c] problem with cc compiler

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