Walter said:
: Even if the linker is able to substitute a user-written
:function for an actual library function, there is no guarantee
:the program will work. Library functions may have private,
:unpublished interfaces with each other, "back doors" into each
thers' operations.
That is a good point, which is of concern with "global" linkers
that examine all the files first before choosing which function
to link to. It turns out, though, not to be a problem with
one-pass linkers unless the user explicitly names the relevant
libraries before they name their object file [and even then,
it turns out not to be a problem for the standard library.]
I think you're missing the point. Let's suppose you decide
to replace malloc(), perhaps the library function that is the
most frequent target of such beyond-the-pale substitution. Are
you stupid enough to replace malloc() alone, without replacing
calloc(), realloc(), and free()? Of course not: you know that
these four functions are a "package," they interoperate with
each other, they manipulate the same undocumented data structures,
and so on. You replace all four functions as an indivisible
unit; you may even go so far as to replace non-Standard functions
like mallinfo() or mallopt() or xmalloc() -- the point is, you
must replace the entire package to have any hope of success.
Ah, but did you remember to replace _io_alloc(), the special
"back door" fopen() and set[v]buf() use to obtain I/O buffers
aligned on page boundaries? Almost certainly not: _io_alloc()
is an implementation-private undocumented function ... which
just happens to depend on the exact details of the undocumented
data structures used by malloc() et al. Drop a different malloc()
into the program, and suddenly your I/O streams start misbehaving
in mysterious ways ...
In one pass linkers, if the user's object file defining [say]
malloc() is placed between their other object files and the
[possibly implicit] reference to the standard C library, then
the user's definition will satisfy any malloc() references in
the user's code; the one-pass linker will then "forget" that it
has seen a definition of malloc() and will proceed onwards.
I'm sure you're describing *something* here, but I can't
make out what it might be. If a linker finds a definition of
function f() in the first module it processes, but then forgets
all about it when processing the second module's references to
f(), you've got a useless linker. C functions can be called
recursively, so the call graph can contain loops: it is not
always possible to place a function definition after all the
references to it.
However, all this speculation about mechanisms is beside the
point, which is that the C Standard forbids the programmer from
using any of the library function names for his own externally-
linked objects and functions. The Standard need not (and does
not) expound on the reasons for the prohibition; it's simply
part of the definition of the language. If you attempt such a
thing (and get away with it), you are not writing "C" but some
other language, "C-with-special-dispensations." And if things
go wrong your recourse is limited, since CWSD has no Standard
you can browbeat the vendor with.