Boehm GC - undefined reference to `GC_malloc'

K

Keith Thompson

August Karlstrom said:
OK, so if libgc did include the prototype for `read' in unistd.h I would
get a compilation error with my example.

Here's the example from upthread that I presume you're referring to:

#include <stdio.h>
#include <gc/gc.h>


void read(void)
{
char *s;

puts("read()");
s = GC_malloc(32);
}


int main(void)
{
read();

return 0;
}

It's not 100% clear what "if libgc did include the prototype for
`read' in unistd.h" means. I presume you mean "if the C source
file that implements part of the gc library and calls read() has
a #include <unistd.h> directive".

In fact, the relevant source file happens to be pthread_support.c,
(which contains the definition of GC_get_nprocs(), which calls read()),
and that source file *does* have a #include <unistd.h>.

No, that doesn't imply that *your* code would get a compilation
error. Your program and pthread_support.c are compiled separately;
neither directly affects the other. If there were a #include
<unistd.h> in <gc/gc.h>, then that would affect the compilation of
your source file -- but there isn't.

The problem is this: Your source file depends on gc, which depends
on POSIX. Your source file defines and uses a function named "read".
POSIX defines another function named "read", and gc calls it.
You've linked together your own object file (generated by compiling
your source file), the gc library, and the POSIX library (probably
part of your system's libc) into an executable, which doesn't work
properly because of the conflicting "read" functions.

The C standard says very little about what happens when you do
something like this (I'm fairly sure the behavior is undefined),
and it's up to you to avoid the problem. C doesn't provide a way to
have support functions with the same name, and it doesn't require
the implementation to tell you when you've tried to use two such
functions within a program. If you're lucky, the linker might warn
you about it, but in this case you weren't lucky.
 
A

August Karlstrom

The C standard says very little about what happens when you do
something like this (I'm fairly sure the behavior is undefined),
and it's up to you to avoid the problem.

This is interesting as there is generally no way I could possibly know
of every identifier in the global namespace.
C doesn't provide a way to
have support functions with the same name, and it doesn't require
the implementation to tell you when you've tried to use two such
functions within a program. If you're lucky, the linker might warn
you about it, but in this case you weren't lucky.

This means I have lost the intellectual control over the program. In my
humble opinion it is a serious flaw in the C language/compiler strategy.

Anyway, thanks Keith for the thorough explanation.


/August
 
I

Ian Collins

This is interesting as there is generally no way I could possibly know
of every identifier in the global namespace.

Which is why there is/are namespace(s) reserved for the the
implementation (strxxxx, __xx etc.).

We can also use static linkage to confine our names to the current
compilation unit. Properly written libraries have all their global
symbols in their headers.
This means I have lost the intellectual control over the program. In my
humble opinion it is a serious flaw in the C language/compiler strategy.

Not really, there are times when you want to be able to interpose over
library functions.
 
A

August Karlstrom

Not really, there are times when you want to be able to interpose over
library functions.

The loyalty of the C programmers towards their language never ceases to
amaze me. ;-)


/August
 
I

Ian Collins

The loyalty of the C programmers towards their language never ceases to
amaze me. ;-)

It's not loyalty, but something I do every day!

Besides, how else can conflicting symbols be resolved?
 
K

Keith Thompson

Ian Collins said:
Which is why there is/are namespace(s) reserved for the the
implementation (strxxxx, __xx etc.).

That doesn't help in this case; the function causing the problem is
read(), which isn't in the implementation-reserved namespace.

August's program uses Boehm's GC; it does not intentionally use
POSIX. But Boehm's GC apparently depends on POSIX *internally*
(it calls read()). The name quietly leaks from POSIX, to GC,
to the program, because names visible to the linker are all in
one namespace.

It would be nice to be able to avoid this kind of thing (other than
by knowing all the external names in all the libraries you're using,
*either directly or indirectly*). But C doesn't provide any such
mechanism, and typically implementations seem not to do so either.
That's a great pity, IMHO.

Unless there's some trick I'm missing. Anyone?

[...]
 
I

Ian Collins

That doesn't help in this case; the function causing the problem is
read(), which isn't in the implementation-reserved namespace.

August's program uses Boehm's GC; it does not intentionally use
POSIX. But Boehm's GC apparently depends on POSIX *internally*
(it calls read()). The name quietly leaks from POSIX, to GC,
to the program, because names visible to the linker are all in
one namespace.

It would be nice to be able to avoid this kind of thing (other than
by knowing all the external names in all the libraries you're using,
*either directly or indirectly*). But C doesn't provide any such
mechanism, and typically implementations seem not to do so either.
That's a great pity, IMHO.

Unless there's some trick I'm missing. Anyone?

I don't think there is. Another unfortunate trap for the unwary. The
only standard tool we have is static symbols.

It isn't only C that has this problem, I have bumped into it with C++ as
well.
 

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

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,175
Latest member
Vinay Kumar_ Nevatia
Top