[comp.lang.c] MSC v5.1 bug; variable not made public

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>.