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>.
NU013809@NDSUVM1.BITNET (Greg Wettstein) (11/12/88)
I have just noticed what appears to be a bug in Codeview and am wondering if anyone on the net has noticed a similar problem. First the hardware configuration I have noted the problem on: ALR 386/220 (80386 processor running at 20 Mhz) 2 Megabyte RAM 80 Megabyte hard disk - drive and controller unknown. Packard Bell EGA video card Phoenix 80385 BIOS 3.07.00 (Mirrored to RAM) Packard Bell 2400 baud internal modem configured for COM2 1 Serial and 1 Parallel Port Software configuration: DOS 3.3 Codeview Version 2.2 MSC Version 5.1 QuickC Version 1.01 MS LINK Version 3.65 (? - Version number may not be exact but it is the Linker supplied with MSC Version 5.1. * All compiler software was installed with the SETUP program supplied with MSC 5.1. Only the small model libraries were selected and the emulator library was selected. (Presence of co-processor detected at run-time and fixups generated, otherwise emulator code used for floating point operations.) Run-time Environemnet: Config.sys entry: FILES = 20 No autoexec.bat file executed. No memory resident programs active. Problem: A program was compiled using the small memory model with both MSC 5.1 and QuickC 1.01. The program consisted of five modules each of which were compiled independently with the following compiler command: (Q)CL /Zi /Od /c (pname.c) where pname is the filename of the source file. The executable file was prepared by linking all five modules together with the following linker command: LINK /CODEVIEW /NOI p1+p2+p3+p4+p5,p1,p1.map,lib1.lib+lib2.lib Where p1-p5 are the names of the modules and lib1-lib2 are object code libraries prepared with MSC 5.1 and continuing various adjunct functions. The Codeview debugger was invoked with the following commands: cv /r p1 * The /r switch instructs Codeview to use the hardware debug registers for setting cv /r /cgmain p1 tracepoint interrupts. In the first case the program was than executed to the program entry point with the following command: g main In both cases after the startup code was executed returning to DOS with the q command resulted in a system hang. The screen would go blank and CTRL-BREAK would elicit no response. The system still seemed to be servicing interrupts since pressing CTL-ALT-DEL would re-boot DOS. The first function of this program is to display an entrance menu. When execution was started with a simple go (g or F5) the program would display display the menu and when the exit command was issued a 'program terminated normally' prompt would be issued and at this time the 'q' command would be result in a normal return to dos. At first I thought this behavior simply resulted from returning to DOS without executing the program termination code. I then allowed the program to execute through several menu levels and then terminate. After this process the computer would hang when a return to DOS was attempted. Has anyone else experienced this difficulty while attempting to use the hardware debug registers with Codeview? I have not tested the bug with other programs but it is quite reproducible with this example. Removing the /r switch when Codeview was executed resulted in complete alleviation of the problem. I would appreciate comments from anyone who has experienced this problem or knows of similar problems with other 80386 processors. Replys to either the net or by e-mail would be fine. Thanks in advance. As always, G.W. Wettstein NU013809@NDSUVM1