wsmith@m.cs.uiuc.edu (08/31/88)
This problem with the BSD linker can cause portability problems for
programs that use programmer created libraries.
Description:
In the BSD C compiler may not complain of multiply defined functions
while in other C compilers will fail to link the same program.
If the only data needed by the linker from a module is a variable
in BSS, multiply defined functions in that same module will be
ignored.
Repeat-By:
Create two files, one.c two.c
one.c:
extern int a;
main()
{
printf("%d\n",a);
}
four() { }
two.c:
int a;
four() { }
If the program is compiled with "cc -o aprog one.c two.c", _four is
reported as multiply defined. However, if the program is compiled with
"cc -c one.c two.c
ar r alib.a two.o
ranlib alib.a
cc -o aprog one.o alib.a" no error will be reported (under BSD).
With other compilers on other operating systems, _four will be multiply
defined in both cases. However, if the first line of two.c is changed to
"int a = 7;", the BSD C compiler will report _four as multiply defined in
both cases. Linking with a library should be equivalent to linking the
individual modules in the library that are needed. In this problematic
case, the equivalence is broken.
Fix: ???
Bill Smith wsmith@cs.uiuc.edu uiucdcs!wsmith
ron@topaz.rutgers.edu (Ron Natalie) (09/01/88)
You're problem is NOT that the _four is not properly reported as being multiply defined, it is that the module two.o isn't loaded at all. The "int a" declaration generates a .com of the appropriate space. Declarations need not force loading of modules with identical declarations. -Ron
mouse@mcgill-vision.UUCP (der Mouse) (09/10/88)
In article <Aug.31.18.45.05.1988.12460@topaz.rutgers.edu>, ron@topaz.rutgers.edu (Ron Natalie) writes: > You're problem is NOT that the _four is not properly reported as > being multiply defined, it is that the module two.o isn't loaded at > all. The "int a" declaration generates a .com of the appropriate > space. Declarations need not force loading of modules with identical > declarations. Except the declarations weren't identical. The explicitly-loaded .o file's declaration was explicitly extern. The one in the library was a non-extern definition (a "tentative" definition). *Some* definition of that variable is needed somewhere, or the loader will (properly) generate an undefined symbol error. The problem is that two.o provides that definition, but the definition is being taken from two.o without including the rest of two.o. I agree with the original poster that this is a bug. der Mouse old: mcgill-vision!mouse new: mouse@larry.mcrcim.mcgill.edu
ron@topaz.rutgers.edu (Ron Natalie) (09/12/88)
> The problem is that two.o provides > that definition, but the definition is being taken from two.o without > including the rest of two.o. I agree with the original poster that > this is a bug. No, no, no. There is a bug, but it is not that only "part" of the file is loaded. The problem is that the file containing the non-externed definition isn't loaded at all. There are essentially two types of C-compilers. Some will take external definitions (whether they have extern before them or not) and generate common blocks for them. The function of a common block is that all references in the .o files are merged into the same area (with an initialization if one is available). For example, these machines will not give an error on the following: a.c: int ex_a; b.c: int ex_a; cc a.c b.c -o out "int ex_a;" and "extern int ex_a;" generate the same code, which looks something like "ex_a: .com 4". Other machines will generate an actual data storage declaration for each of those un-externed declarations. They rely on the rule in C that says that only one actual definition occurs and the rest be "externed." The problem is the user has the commonizing compiler. Normally that behavior is OK, in that even if you do use the extern for n-1 definitions rule, the code will work. The problem is that if you put a module into a library it treats the "un-externed" reference as just another instance of the common block and doesn't cause that to force the module to be loaded. I get bitten by this periodically. -Ron