ldh@hcx1.SSD.HARRIS.COM (02/02/89)
Here's one for the UNIX gurus who also know something about TurboC ... Have a modularized program lint/cc do not object to the various modules ... TC2 on the other hand does. basically: header.h: #include <stdio.h> #include < > (a bunch of includes) int a,b,c,d,e,f,g,h; float i,j,k,l,m,n,o,p; char q,r,s,t,u,v; struct (a few) #define ABC abc (a few) main.c: #include "header.h" main() { /* some program */ } module_a.c: #include "header.h" function abc() { } module_b.c #include "header.h" function def() { } When invoked as follows, the TurboC 2.0 linker has a 2 major objections: tlink \tc2\lib\c0m main module_a module_b,prog,prog,,\tc2\lib\cm 1) variables defined in header.h get linker error messages as follows: Error: _A defined in module MAIN.C is duplicated in module MODULE_A.C Error: _A defined in module MAIN.C is duplicated in module MODULE_B.C 2) Certain basic stuff ends up being "undefined" Undefined symbol '_FOPEN' in module MAIN.C Undefined symbol '_PRINTF' in module MAIN.C What is going on?! This is the first time I have tried anything modularized on TC2 ... Any assistance would be greatly appreciated Leo Hinds ldh@hdw.harris.com
mark@jhereg.Jhereg.MN.ORG (Mark H. Colburn) (02/03/89)
In article <44100021@hcx1> ldh@hcx1.SSD.HARRIS.COM writes: >Have a modularized program lint/cc do not object to the various modules ... TC2 >on the other hand does. > >basically: > >header.h: >#include <stdio.h> >#include < > (a bunch of includes) > >int a,b,c,d,e,f,g,h; >float i,j,k,l,m,n,o,p; >char q,r,s,t,u,v; Each of these declarations reserve a slot of memory for the variable being declared. The amount of memory, obviously depends on the type of the declaration. You later include this file into mutliple compilation units (modules). The result is: main.c: int a,b,c,d....; module_a: int a,b,c,d....; Which saves slot of memory for "int a,b..." in both main.c and module_a.c. When you try to link the programs together, the linker complains. What you should have, if you want a,b,c,d, etc. to be global variables is: main.c: int a,b,c,d...; module_a: extern int a,b,c,d....; The fact the your unix compiler/linker does not catch this error is actually just sloppy play on your compiler vendors part. Multiple declarations of this sort usually indicate a bug in the program somehere. If the linker does not complain, they can be very difficult to track down. Hope that this helps. -- Mark H. Colburn "Look into a child's eye; Minnetech Consulting, Inc. there's no hate and there's no lie; mark@jhereg.mn.org there's no black and there's no white."
maart@cs.vu.nl (Maarten Litmaath) (02/03/89)
ldh@hcx1.SSD.HARRIS.COM writes:
\header.h:
\#include <stdio.h>
\#include < > (a bunch of includes)
\int a,b,c,d,e,f,g,h;
\float i,j,k,l,m,n,o,p;
\char q,r,s,t,u,v;
Aaaaaaaaargh! A header file should NEVER contain variable DEFINITIONS!
It should only contain `#define's and variable DECLARATIONS.
So:
extern int a, ...;
extern float i, ...;
extern char q, ...;
The definitions are handled in an accompanying file `header.c'.
A nice solution to prevent redundancy (and error-proneness):
#ifndef HEADER_H
#define HEADER_H
#ifndef EXTERN
#define EXTERN extern
#else EXTERN
#define INIT
#endif !EXTERN
EXTERN int a, ...;
EXTERN float i, ...;
EXTERN char q[]
#ifdef INIT
= "hey babe!"
#endif INIT
;
#endif !HEADER_H
In `foo.c':
#include "header.h"
In `header.c':
#define EXTERN
#include "header.h"
--
"Does she play, er, tennis? |Maarten Litmaath @ VU Amsterdam:
Wink wink, notch notch!" |maart@cs.vu.nl, mcvax!botter!maart
bkbarret@sactoh0.UUCP (Brent K. Barrett) (02/03/89)
In article <44100021@hcx1>, ldh@hcx1.SSD.HARRIS.COM writes: > > Here's one for the UNIX gurus who also know something about TurboC ... > > Have a modularized program lint/cc do not object to the various modules ... TC2 > on the other hand does. > [ Chomp! ]j > When invoked as follows, the TurboC 2.0 linker has a 2 major objections: > tlink \tc2\lib\c0m main module_a module_b,prog,prog,,\tc2\lib\cm > > > 1) variables defined in header.h get linker error messages as follows: > Error: _A defined in module MAIN.C is duplicated in module MODULE_A.C > Error: _A defined in module MAIN.C is duplicated in module MODULE_B.C > > 2) Certain basic stuff ends up being "undefined" > Undefined symbol '_FOPEN' in module MAIN.C > Undefined symbol '_PRINTF' in module MAIN.C > > What is going on?! This is the first time I have tried anything modularized on > TC2 ... Turbo C allows global variables to be declared only ONCE. Every other time they are included in a module, they must be declared as "extern"als. Do the following to solve your problem: 1) Place all your variable declarations into your main.c file as is, then create a file called "extern.h" that lists the same variable declarations prefixed by "extern." e.g.: float j; becomes: extern float j; 2) simply #include "extern.h" in all your modules except main.c. I'm no Unix guru, but that will solve your TC problems. -- "Somebody help me! I'm trapped in this computer!" Brent Barrett ..pacbell!sactoh0!bkbarret GEMAIL: B.K.BARRETT
ldh@hcx1.SSD.HARRIS.COM (02/03/89)
Thanks to all that responded ... I had infact done as most suggested (use the extern) ... someone also suggested the use of "static" ... the main concern I had there was whether TurboC was right or the UNIX cc/lint was, and therefore who should I trust in the future. In my linking problem, someone suggested that I include \lib\mathX ... but the linker errors involved basics like _printf ... that one still is a problem ... any suggestions will still be greatly appreciated. Thanks :-) Leo Hinds ldh@hdw.harris.com
swh@hpsmtc1.HP.COM (Steve Harrold) (02/03/89)
Re: TLINK vs lint Try using the /c switch on the TLINK command line. This forces the linker to honor mixed case symbols. As you've posted it, all symbols are forced to uppercase with the result that your program's reference to "fopen" got translated to a reference to "FOPEN" which got translated to a reference to "_FOPEN" which is not present in the libraries. ("_fopen" is). -- --------------------- Steve Harrold ...hplabs!hpsmtc1!swh HPG200/13 (408) 447-5580 ---------------------
chris@mimsy.UUCP (Chris Torek) (02/06/89)
[re def/ref vs common, where the `extern' in foo.c: int a; bar.c: /* extern */ int a; matters] In article <508@jhereg.Jhereg.MN.ORG> mark@jhereg.Jhereg.MN.ORG (Mark H. Colburn) writes: >The fact the your unix compiler/linker does not catch this error is >actually just sloppy play on your compiler vendors part. Multiple >declarations of this sort usually indicate a bug in the program somehere. Hardly. The Unix compilers and linkers use the `common model', in which a declaration without `extern' and without an initial value compiles to a FORTRAN-common-style definition, such as .comm _a,4 for int a; (the 4 here is the size of `a' in bytes). Other compilers use the more restrictive `def/ref model': _a: .long 0 for `int a' (and `int a = 0') and .extern _a for `extern int a'. The def/ref model *can* catch bugs like this one: foo.c: int status; bar.c: struct { char *msg; int code; } status; but I prefer the common model. Lint catches the above bug, and the def/ref compiler does *not* catch the bug if one writes instead foo.c: int status; bar.c: extern struct { char *msg; int code; } status; or (if extern declarations carry size information but sizeof(int)==sizeof(char *)) foo.c: int status; bar.c: extern char *status; so one must run lint anyway. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
ldh@hcx1.SSD.HARRIS.COM (02/08/89)
Thanks to all that responded to my querries ... Someone suggested that I should try the /c (case sensitive link) in the tlink run ... that changed the "undefined _FOPEN" to "undefined _fopen" ... Another suggestion was "why mess with TLINK ... let TCC figure it out" ...sure enough, by now doing TCC -eoutput $(OBJFILES) will now correctly invoke TLINK and I get an executablethat I can actually run ... Thanks to all that responded ! Leo Hinds