evas@euraiv1.UUCP (Eelco van Asperen) (11/02/88)
Hi,
I've just found a nice bug in MSC v5.1; if you declare an unitialized
variable in a module that has no other publics and put that module in
a library, the variable will _not_ be found by LINK. Here's a small
example;
File alfa.c:
char alfa[1000];
proc_alfa() {}
File beta.c:
extern char alfa[];
main()
{
strcpy(alfa,"This is a bug !");
#ifdef CALL_ALFA
proc_alfa();
#endif
puts(alfa);
exit(0);
}
compile this;
cl -c alfa.c beta.c
create a library;
lib demo +alfa;
and try to link;
link /noi beta,,,demo;
and bingo;
Microsoft (R) Overlay Linker Version 3.65
Copyright (C) Microsoft Corp 1983-1988. All rights reserved.
LINK : error L2029: Unresolved externals:
_alfa in file(s):
BETA.OBJ(beta.c)
There was 1 error detected
Now, I did not insert that #ifdef in beta.c for nothing; let's recompile
with -DCALL_ALFA;
cl -DCALL_ALFA -c beta.c
link /noi beta,,,demo;
and everything is fine.
To determine what caused the error, I did the same for TurboC v1.5;
tcc -c alfa.c beta.c
lib demo +alfa;
link \tc\lib\c0s beta,beta,,demo \tc\lib\cs;
and hey, no errors !
I then used OBJSNOOP to peek in the OBJ-files to see what publics they
contained and sure enough the TurboC version contained _alfa while the
MSC version did not;
TurboC:
---------- alfa.obj
public _alfa
public _proc_alfa
MSC:
---------- alfa.obj
extrn __acrtused
extrn __chkstk
extrn _proc_alfa
public _proc_alfa
The same thing happens if 'alfa' is an int; however, if you initialize
'alfa', then everything will work ok. For example;
char alfa[] = "Just a test!";
Peeking with OBJSNOOP at ALFA.OBJ shows;
---------- alfa.obj
extrn __acrtused
extrn __chkstk
extrn _proc_alfa
public _alfa
public _proc_alfa
I realize that this is a pathetic example but I was bitten by it and
it took me an hour to find why the *****y linker could not find two
global arrays I had declared in a separate file with no other entries.
(and then another half hour to document it, try alternatives and
write this ;-)
--
Eelco van Asperen. EUR/Rotterdam/Netherlands
uucp: evas@eurtrx / mcvax!eurtrx!evas earn/bitnet: asperen@hroeur5
"We'd like to know a little bit about you for our files"
- Mrs.Robinson, Simon & Garfunkel
creps@silver.bacs.indiana.edu (Steve Creps) (11/03/88)
In article <792@euraiv1.UUCP> evas@euraiv1.UUCP (Eelco van Asperen) writes: >I've just found a nice bug in MSC v5.1; if you declare an unitialized >variable in a module that has no other publics and put that module in >a library, the variable will _not_ be found by LINK. Here's a small That problem is also in MSC 4.0. I too noticed that initializing the variable makes the problem go away. It's also possible that the bug is actually in LIB, as the uninitialized variable still shows up in the .obj file when I do a strings on it. - - - - - - - - - - Steve Creps, Indiana University, Bloomington, home of the "Hoosiers" creps@silver.bacs.indiana.edu (129.79.1.6) {inuxc,rutgers,uunet!uiucdcs,pur-ee}!iuvax!silver!creps creps@iubacs.bitnet (forwarded)
allbery@ncoast.UUCP (Brandon S. Allbery) (11/10/88)
As quoted from <792@euraiv1.UUCP> by evas@euraiv1.UUCP (Eelco van Asperen): +--------------- | I've just found a nice bug in MSC v5.1; if you declare an unitialized | variable in a module that has no other publics and put that module in | a library, the variable will _not_ be found by LINK. Here's a small | example; +--------------- It's not a bug. Believe it or not, it's a feature. The idea is to be able to load variant versions of functions based on what is used by a program. It applies *only* to programs. I should note that UN*X "ld" acts the same way (but Minix "asld" does *not*, which explains why the following example doesn't work under Minix). An example of why this is useful is "stdio", as implemented by UN*X and possibly by the MSC library. Basically, the C start-up "stub" calls the function "main" (which is your main program function) and passes the return value to the function "exit". Now, IF YOU USE stdio, the exit() function has to call another function (usually called _cleanup()) to flush stdio buffers. If you DON'T use stdio, the function _cleanup() must NOT be called or stdio will be dragged into your program for no purpose and waste space. The solution is that the linker watches for the use of multiple externs in files in some way which I'm not really familiar with. The effect I do know: if you don't reference any other stdio functions, the linker will use the non-stdio exit(). If you reference any of the other functions, they will force the loading of the stdio version of exit(). Your problem is that the extern variable isn't enough to force the loading of the source file where it is declared. When you add the function call, it forces LINK to load the file containing it and "drags in" the extern at the same time. (Thus, you could have a number of different variables with the same name declared in that way in the library, but function calling patterns would determine which one actually got linked into the program.) I suggest that the best place to find out about this aspect of linkers is comp.unix.questions, since it's a question that comes up every so often about the UN*X linker. ++Brandon -- Brandon S. Allbery, comp.sources.misc moderator and one admin of ncoast PA UN*X uunet!hal.cwru.edu!ncoast!allbery <PREFERRED!> ncoast!allbery@hal.cwru.edu allberyb@skybridge.sdi.cwru.edu <ALSO> allbery@uunet.uu.net comp.sources.misc is moving off ncoast -- please do NOT send submissions direct Send comp.sources.misc submissions to comp-sources-misc@<backbone>.
allbery@ncoast.UUCP (Brandon S. Allbery) (11/10/88)
As quoted from <12886@ncoast.UUCP> by allbery@ncoast.UUCP (Brandon S. Allbery): +--------------- | The idea is to be able to load variant versions of functions based on what | is used by a program. It applies *only* to programs. I should note that +---------------------------------------------^^^^^^^^ AAAACK!!! Sorry, people; I guess brain rot is setting in. :-( I meant: "It applies *only* to LIBRARY FILES". ++Brandon -- Brandon S. Allbery, comp.sources.misc moderator and one admin of ncoast PA UN*X uunet!hal.cwru.edu!ncoast!allbery <PREFERRED!> ncoast!allbery@hal.cwru.edu allberyb@skybridge.sdi.cwru.edu <ALSO> allbery@uunet.uu.net comp.sources.misc is moving off ncoast -- please do NOT send submissions direct Send comp.sources.misc submissions to comp-sources-misc@<backbone>.