Library functions

  • Thread starter amit.codename13
  • Start date
A

amit.codename13

does defining a function with the same name as one of the standard
library functions invoke undefined behavior?
 
E

Eric Sosman

does defining a function with the same name as one of the standard
library functions invoke undefined behavior?

Yes, unless the new function is `static' and none of the
headers that declare the Standard's function is included.
 
O

osmium

Eric Sosman said:
Yes, unless the new function is `static' and none of the
headers that declare the Standard's function is included.

What a weird rule! That says the compiler is not independent of the
libraries as is sometimes claimed on this newsgroup.
 
A

amit.codename13

     Yes, unless the new function is `static' and none of the
headers that declare the Standard's function is included.

int putchar(int c);

static void printf(char * str)
{
putchar('H');
putchar('e');
putchar('l');
putchar('l');
putchar('o');
}


int main()
{
printf("Hi");
return 0;
}

Is the code above strictly conforming code?
 
O

osmium

Richard Heathfield said:
osmium said:


In that circumstance, whatever behaviour the implementation decides
on is acceptable, so it's hard to see how you drew that conclusion.

I have no idea what "that circumstance" is, nevertheless I will respond to
the last part of your sentence.
I drew the conclusion that the compiler was not independent of the libraries
from the statement that making them invisible is not enough. You must also
make the user defined function static. Therefore the compiler must know the
name of a set of "special" functions. It seems that the actual problem
might be in the linker, but the effect on the programmer is identical. It
is customary, as you know, to use "compiler" as shorthand for "the
implementation" or whatever.

The end result is the programmer must memorize a whole bunch of special
words or be prepared for surprises.
 
J

jameskuyper

osmium said:
I have no idea what "that circumstance" is, nevertheless I will respond to
the last part of your sentence.
I drew the conclusion that the compiler was not independent of the libraries
from the statement that making them invisible is not enough. You must also
make the user defined function static. Therefore the compiler must know the
name of a set of "special" functions.

You misunderstand the import of "undefined behavior". It does not
impose requirements on the compiler, but on the user. The compiler is
not required to notice that the function has the same name.
It seems that the actual problem
might be in the linker,

The linker is part of the implementation; it's only the implementation
as a whole that is governed by the C standard. The problem that the
linker may have is precisely the problem that is allowed by the fact
the standard says that the behavior is undefined.
but the effect on the programmer is identical. It
is customary, as you know, to use "compiler" as shorthand for "the
implementation" or whatever.

That custom hides the fact that the compiler is generally not the
complete implementation. It's not possible to completely implement the
C language on most computer systems without combining features provide
by the compiler, the linker, the operating system, and the hardware
that they are attached to.
 
F

Flash Gordon

Please don't quote peoples sigsm the bit typically after the "-- "
unless you aerr commenting on them.
int putchar(int c);

static void printf(char * str)
{
putchar('H');
putchar('e');
putchar('l');
putchar('l');
putchar('o');
}


int main()
{
printf("Hi");
return 0;
}

Is the code above strictly conforming code?

Looks fine to me.
 
F

Flash Gordon

osmium said:
What a weird rule! That says the compiler is not independent of the
libraries as is sometimes claimed on this newsgroup.

It depends on what specific claims you are referring to. If you are
referring to claims that gcc does not come with a library then they are
true but irrelevant to this discussion.

The header could define a macro implementation of the function, and this
would obviously interfere with any user attempt to define a function of
the same name if the header is included. If the user defined function is
not static then you have two functions with external linkage (visible
outside that specific translation unit) so which one will be called by
the rest of the program and will the linker even allow it?

The standards committee probably decided to allow a user defined
function declared as static with none of the headers included because
the name of the user defined function is not visible outside that
translation unit, so this is easy to handle.
 
O

osmium

"jameskuyper" write:
You misunderstand the import of "undefined behavior". It does not
impose requirements on the compiler, but on the user. The compiler is
not required to notice that the function has the same name.


The linker is part of the implementation; it's only the implementation
as a whole that is governed by the C standard. The problem that the
linker may have is precisely the problem that is allowed by the fact
the standard says that the behavior is undefined.


That custom hides the fact that the compiler is generally not the
complete implementation. It's not possible to completely implement the
C language on most computer systems without combining features provide
by the compiler, the linker, the operating system, and the hardware
that they are attached to.

Thank you for your helpful answer. The other answers I was getting made me
think I had entered the land of Oz. Talk a lot, use short sentences, but
don't say anything that might be helpful

I guess I didn't realize that it was impossible to do it the way I would
like to see it. I can see the difficulty if the implementation had to use a
linker, as comes with a main frame. I thought with PCs there was a new era,
I guess that's where I went wrong.
 
E

Eric Sosman

osmium said:
What a weird rule!

Weird or not, you can read it for yourself in 7.1.3p1.
That says the compiler is not independent of the
libraries as is sometimes claimed on this newsgroup.

This newsgroup is not devoid of ill-informed, foolish,
and even malicious claims.

Consider, though: One reason you *want* the compiler to
have "special knowledge" of library functions (or at least to
be allowed to have such knowledge) is to allow the compiler
to generate optimized code. You write a call to the memset()
function, and the compiler might generate a few instructions
in-line instead of calling a function. You write a call to
the sqrt() function, and the compiler might generate a SQRT
opcode. You write printf("Hello, world!\n") and the compiler
might generate code for puts("Hello, world!").

Also, it may turn out that the library functions interact
with each other in non-obvious ways. Some interactions are
apparent: for example, fopen() and fclose() affect the
behavior of exit(). Others may be invisible to the programmer:
Perhaps fopen() acquires buffer space via a private "back door"
in the malloc() suite, or the code implementing VLA's has built-
in knowledge of the data structures that manage the heap.

Summary: The Standard library functions are part of the
implementation (in a hosted environment), and "belong" to it.
You intrude on the implementation at your peril. ("Meddle not
in the affairs of wizards, for they are subtle and quick to
anger." -- JRRT)
 
E

Eric Sosman

int putchar(int c);

static void printf(char * str)
{
putchar('H');
putchar('e');
putchar('l');
putchar('l');
putchar('o');
}


int main()
{
printf("Hi");
return 0;
}

Is the code above strictly conforming code?

Yes. (Unless I've missed something.)
 
R

Richard Bos

osmium said:
What a weird rule! That says the compiler is not independent of the
libraries as is sometimes claimed on this newsgroup.

That would be because that claim is at worst dishonest and at best
simply wrong.

Richard
 
K

Keith Thompson

osmium said:
I guess I didn't realize that it was impossible to do it the way I
would like to see it. I can see the difficulty if the
implementation had to use a linker, as comes with a main frame. I
thought with PCs there was a new era, I guess that's where I went
wrong.

Every C implementation I've ever seen requires a linker.
 
O

osmium

Keith Thompson said:
Every C implementation I've ever seen requires a linker.

That was my point - and my error. Every PC I know about has its *own*
linker, designed and budled for *that* compiler. In a main frame I wouldn't
expect that to be true. I have used C on a main frame but only very
briefly. As long as the compiler writer can control the linker (by
specifying it) I see no need for this restrction. But the C *language* does
not, and very possibly could not, certainly should not, specify that
constraint. So the language specification has to work within the
restrictions, side effects, and so on of the (computer) vendor's product -
collector, or whatever it's called in a given culture. If they require a
function be declared static, they can hide it from the linker.


This may not be a very real problem for 99+% of the programs written, but
still, it IS a rule. I wrote a personal version of a sin(x) function
ignoring the "static" rule and it worked fine in my environment.
 
C

CBFalconer

osmium said:
What a weird rule! That says the compiler is not independent
of the libraries as is sometimes claimed on this newsgroup.

I see nothing weird. I do see provisions to control the function
actually called.
 
A

Amandil

What a weird rule! That says the compiler is not independent of the
libraries as is sometimes claimed on this newsgroup.

There is a very good reason for that. Consider the following:

/* File A.c */
extern int write(int, char*, int);
/* Standard POSIX write() exists on this system */

void printf(int fd, char *buf, int siz)
{
write(fd, buf, siz);
return;
}
/* End File A.c */

/* File B.c */
#include <stdio.h>

int main(void)
{
printf("Which function gets called?\n");
}
/* End File B.c */

And compile with a command similar to:
cc B.c A.c write.c

The linker (which is needed when compiling two files) will almost
definitely barf in disgust when seeing this. Which printf() is meant?
The externally defined printf() from file A.c? Or the standard printf
() declared in stdio.h? To protect you from making this mistake, the
standard tells you that file A.c, which declares (and defines) its own
function named printf(), invokes undefined behavior - in this case,
probably a linker error.

In truth, even if file B.c did not #include stdio.h, the linker might
regurgitate this program, as it may be the policy of this compiler to
link all programs to the entire standard C library, which already
includes a function named printf(). Having two functions, both with
external declaration, with the same name, could very reasonably be
called "undefined behavior" - again, probably a linker error.

If the printf() is declared as static, then - for obvious reasons -
there is no longer any conflict of names. Consequently, Mr. Sosman
tells us (quoting the Standard, I assume) that such a program is
legal.

For the nitpickers out there, calling write() from my program does not
make it nonstandard. write() is a user-defined function in a different
file, which for whatever reason I have not posted. I am only telling
you that it works the same way as the standard POSIX function of the
same name.

-- Marty Amandil
"Go not to c.l.c for answers, for they will say both yes and no."
 
E

Eric Sosman

osmium said:
[... about replacing Standard library functions ...]

This may not be a very real problem for 99+% of the programs written, but
still, it IS a rule. I wrote a personal version of a sin(x) function
ignoring the "static" rule and it worked fine in my environment.

"Undefined behavior" includes "it worked fine" among
the possible outcomes.

Many environments do in fact allow Standard libarary
components to be replaced, within reason -- for example, it
it would be folly to replace malloc() without replacing free()
at the same time. When such flexibility is available, the
programmer can often use it to advantage.

But not all environments can offer this capability. I
recall one, for example, in which the Standard library was an
all-or-nothing proposition: You could replace one part of the
library only if you replaced *all* the parts you used, because
as soon as you used just one Standard feature (stdout or errno,
for example), you pulled in the entire library.

Even when an implementation allows function replacement
you must use some caution. I mentioned the interrelationship
of malloc() and free(), which are "obvious even to the casual
observer," but a library may have less overt interrelationships
and is under no obligation to document them. For example, you
might replace malloc() and friends and use your mixed-mode
setup with success -- right up until the moment when you create
your first variable-length array and discover that the generated
code "knows" about malloc()'s data structures ...
 
A

amit.codename13

[...]


int putchar(int c);
static void printf(char * str)
{
    putchar('H');
    putchar('e');
    putchar('l');
    putchar('l');
    putchar('o');
}
int main()
{
    printf("Hi");
    return 0;
}
Is the code above strictly conforming code?

Almost.  I see two or three subtle problems.

First, "int main()" should be "int main(void)".  (I've argued at some
length that an implementation needn't support "int main()" without the
void keyword.  I don't want to re-hash the argument; I can try to find
a message-id if anyone is curious.)  This is extremely unlikely to be
a problem in practice, but the question was whether the code is
strictly conforming, so a pedantic answer is warranted.

Second, the output is not terminated with a new-line.  C99 7.19.2p2,
discussing text streams, says:

    Whether the last line requires a terminating new-line character is
    implementation-defined.

If an implementation does require a terminating new-line, and the
program doesn't provide one, then the behavior is undefined (simply
because the standard doesn't define the behavior).

Third, it's always possible for an input or output operation to fail.
putchar('H') can either write the character 'H' to stdout or fail and
return EOF.  When this is taken into account, no program that performs
input or output can be strictly conforming, which probably was not the
intent.

The first two issues are easily corrected, and the third can be
ignored, or at least handwaved away, unless you want to be *really*
pedantic.

In particular, declaring "int putchar(int c)" rather than using
"#include <stdio.h>", and declaring your own static function called
"printf", are not problems as far as strict conformance is concerned.
Of course they're both horribly bad style, but that wasn't the
question.

Incidentally, gcc gives me a warning:

c.c:3: warning: conflicting types for built-in function 'printf'

That's ok; compilers can warn about anything they like, as long as
they produce at least one diagnostic for any translation unit
containing a syntax error, constraint violation, or #error directive.

--
Keith Thompson (The_Other_Keith) (e-mail address removed)  <http://www.ghoti.net/~kst>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
(I've argued at some
length that an implementation needn't support "int main()" without the
void keyword. I don't want to re-hash the argument; I can try to find
a message-id if anyone is curious.)

i am indeed curious.

well may be not worth a discussion but how did you actually know that
my program ended without a terminating new-line character in my post.

Thanks for answering.
i really wanted pedantic answers...
 
A

amit.codename13

[...]


int putchar(int c);
static void printf(char * str)
{
    putchar('H');
    putchar('e');
    putchar('l');
    putchar('l');
    putchar('o');
}
int main()
{
    printf("Hi");
    return 0;
}
Is the code above strictly conforming code?

Almost.  I see two or three subtle problems.

First, "int main()" should be "int main(void)".  (I've argued at some
length that an implementation needn't support "int main()" without the
void keyword.  I don't want to re-hash the argument; I can try to find
a message-id if anyone is curious.)  This is extremely unlikely to be
a problem in practice, but the question was whether the code is
strictly conforming, so a pedantic answer is warranted.

Second, the output is not terminated with a new-line.  C99 7.19.2p2,
discussing text streams, says:

    Whether the last line requires a terminating new-line character is
    implementation-defined.

If an implementation does require a terminating new-line, and the
program doesn't provide one, then the behavior is undefined (simply
because the standard doesn't define the behavior).

Third, it's always possible for an input or output operation to fail.
putchar('H') can either write the character 'H' to stdout or fail and
return EOF.  When this is taken into account, no program that performs
input or output can be strictly conforming, which probably was not the
intent.

The first two issues are easily corrected, and the third can be
ignored, or at least handwaved away, unless you want to be *really*
pedantic.

In particular, declaring "int putchar(int c)" rather than using
"#include <stdio.h>", and declaring your own static function called
"printf", are not problems as far as strict conformance is concerned.
Of course they're both horribly bad style, but that wasn't the
question.

Incidentally, gcc gives me a warning:

c.c:3: warning: conflicting types for built-in function 'printf'

That's ok; compilers can warn about anything they like, as long as
they produce at least one diagnostic for any translation unit
containing a syntax error, constraint violation, or #error directive.

--
Keith Thompson (The_Other_Keith) (e-mail address removed)  <http://www.ghoti.net/~kst>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
(I've argued at some
length that an implementation needn't support "int main()" without the
void keyword. I don't want to re-hash the argument; I can try to find
a message-id if anyone is curious.)

i am indeed curious.

well may be not worth a discussion but how did you actually know that
my program ended without a terminating new-line character in my post.

Thanks for answering.
i really wanted pedantic answers...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,431
Messages
2,571,679
Members
48,796
Latest member
Greg L.

Latest Threads

Top