delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1994/12/08/22:26:46

Date: Thu, 8 Dec 94 09:13 PST
From: jdp AT polstra DOT com (John Polstra)
To: djgpp AT polstra DOT com
Subject: Large g++ object files: solution

I've seen several postings here referring to the "bug" in g++ that
causes uninitialized variables such as:

	char buf[32768];

to be placed in the data section rather than in COMMON.  This makes object
files and executables very large, and people have been complaining about
it.

I just want to point out that (a) g++ does this on purpose, and (b)
there is a compiler option to make it do what you want it to do.

The compiler option is "-fconserve-space".  It was introduced in version
2.6.0, which means that it is available in the compiler that comes
with djgpp112.  From the GNU documentation, under "Options Controlling
C++ Dialect":

===============================================================================
`-fconserve-space'
     Put uninitialized or runtime-initialized global variables into the
     common segment, as C does.  This saves space in the executable at
     the cost of not diagnosing duplicate definitions.  If your program
     mysteriously crashes after `main()' has completed, you may have an
     object that is being destroyed twice because two definitions were
     merged.
===============================================================================

You have to be careful if you use this option.  With it, you can violate
the C++ "one definition" rule, and that won't be detected at link time.
For example, suppose that in a header file you declare a global instance
of some class that has a constructor and destructor:

    class Big {
    public:
	Big();
	~Big();

    private:
	char data[32768];
    };

    Big theBig;	// With "-fconserve-space", this will go into COMMON

Now if you include the header file in several ".cc" files and link them
together, you'll get just a single instance of "theBig", in COMMON.  But
that instance will get constructed and destructed multiple times --
i.e., once per ".cc" file that included the header file.  That is
because you have broken the "one definition" rule, and the linker
(because of "-fconserve-space") wasn't able to detect it.

To make sure this doesn't happen, you need to arrange things so that
your program contains one and only one non-extern declaration of every
global variable.  One way to do that is like this.  In your header file,
say, "global.h", declare your global variables like this:

    #ifndef COMMON // {
    #define COMMON extern
    #endif // }

    COMMON Big theBig;
    COMMON Big anotherBig;
    COMMON char buffer[18000];

You can include "global.h" in as many of your modules as you wish;
all the declarations will have "extern" in front of them, and everything
will be OK.  Now make one special module, say "global.cc" whose purpose
is to *define* the global variables.  That file should look like this:

    #define COMMON		// empty
    #include "global.h"

(You don't HAVE to do this in a special module.  You could also do it,
say, in the module that contains your main() function.)

It's really worth it to browse the compiler documentation.  There are
options out the wazoo to control just about everything you'd like to
control.

   John Polstra                                       jdp AT polstra DOT com
   John D. Polstra & Co., Inc.                   Phone (206) 932-6482
   Seattle, Washington USA                         Fax (206) 935-1262
   "Self-knowledge is always bad news."                 -- John Barth

- Raw text -


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