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