delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1998/11/05/02:46:29

Date: Thu, 5 Nov 1998 09:46:29 +0200 (IST)
From: Eli Zaretskii <eliz AT is DOT elta DOT co DOT il>
X-Sender: eliz AT is
To: djgpp AT delorie DOT com
Subject: Re: Issues making and using libs
In-Reply-To: <364132d1.31058536@news.cis.yale.edu>
Message-ID: <Pine.SUN.3.91.981105092238.2883M-100000@is>
MIME-Version: 1.0
Reply-To: djgpp AT delorie DOT com

On Thu, 5 Nov 1998, Mapson wrote:

> IOW, if I have 25 functions in a lib, and my program only needs 2 of
> them, only the object code for two functions is extracted from the
> lib.

This is correct.  But please note the cricual gotcha:  ``only needs 2
of them'' must mean that the program doesn't reference any of the other
23 functions in any way in the code.

For example, if the code says something like this:

	if (they_want_function_number_23)
	  function_number_23 ();

then the linker will link in function_number_23 even if this condition 
never fires at run time.

> Problem with my theory: the final executables made with the libs
> are *considerably* (20%) larger than the same programs with the raw
> source code (all 25 functions) built in!

Did you strip the executables?  If not, the overhead of the debug info 
in the executable completely overshadows the actual amount of code.

> I used to keep my global variables in my header files- but in
> the case of these libs, they only cause "multiple declaration" errors
> later on- even when I uses the standard "#IFDEFINED _THIS_LIB_ ... way
> of only including things once.

This is a known problem in C.  Several solutions exist (see below), but 
none of them are elegant, IMHO.

> Solution was to pull all variables out
> of the include files, put them in the source files for the libs.

This is a wrong solution, IMHO.  It puts an additional burden on the 
maintainer: if you ever change the declaration of a variable, you will 
need to edit all the places where it is declared, instead of just one 
header.

A better solution is to leave those variables in the header, but declare 
them like this:

	extern int foo
	#ifdef extern
			= 1
	#endif
			   ;

And then have only one library module, the one that doesn't make sense 
without this variable, to include the header like this:

	#define extern
	include "foo.h"
	#undef extern

(The "ifdef extern" part above is only required if you need to initialize
the variable; otherwise you can omit it.)

This setup causes a single module to define a variable and the rest 
declare it as extern, which is exactly what will make the linker happy.

> Problem: I don't understand why this is true with variables and not
> functions- that is, the declared functions certainly don't cause any
> problem.

There's a difference between _declaration_ and _definition_.  This is a 
declaration of a variable:

	extern int foo;

This is a definition of the same variable:

	int foo;

This is a declaration of a function:

	extern int foo (void);

This is a definition of the same function:

	int foo (void) {}

Try to put the last definition in a header and include that header in 
more than a single source file, and the linker will yell bloody murder.

> theory is that the variables, being global, all are given a default
> compiler value ( globals are set to zero by default, right?), and that
> is why the multiple declaration errors occur- it is as if each
> occurance, rather than a declaration, is also a value assignment.

No, that's not the real reason.  The *real* reason is that a definition 
causes the compiler to instruct the linker to assign an address for that 
variable, and the linker will complain when it is required to assign two 
different addresses to the same symbol.

In contrast, a declaration only causes an unresolved external symbol to 
be emitted by the compiler (which the linker resolves at link time, by 
putting an address there).

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019