Introduction

There are a number of reasons why object files, executable files, and libraries may be larger than expected; principal among these are:

Below, we discuss techniques for reducing the impact of these overheads, and ultimately, a technique for compressing executable files, in order to minimize file size.

Avoiding Inclusion of Debugging Information

Perhaps, the most common reason for executables being larger than expected, is that they include debugging information ; (this is added to the object modules, when source files are compiled with GCC’s “-g” option). Even when your own source files are compiled without  the “-g” option, libraries which are linked into your executable may have been compiled with it; (this may be the case, even for the system libraries which are distributed with MinGW).

To exclude debugging information from your executable, simply use the “strip” command to remove it:

C:\project> strip example.exe

Alternatively, use GCC’s “-s” option when linking:

C:\project> gcc -s example.o -o example.exe

Reducing C++ Exception Handling and Run‑Time Type Information Overheads

By default, when compiling C++ code, GCC will compile in support for handling of C++ exceptions, and for interpretation of run‑time type information (RTTI).

If your application does not use either of these, then you may choose to eliminate the overhead incurred by inclusion of the supporting infrastructure code, by compiling and linking with GCC’s “-fno‑exceptions”, and “-fno‑rtti” options, to eliminate the C++ exception handling, and RTTI interpretation overheads, respectively.

Understanding the Effect of C++ Template Classes and the C++ Standard Library

When you use C++ template classes, either defined by yourself, or imported from the C++ Standard Template Library (STL), the compiler generates code separately for each instantiation (e.g. vector<int> and vector<string>), so the total code size can increase significantly. Other elements of the standard C++ library, such as iostreams classes, exception handling classes, and classes such as std::string introduce further overheads, which may seem large in comparison to the size of small applications, (such as “Hello World” type programs).

In practice, these overheads are unavoidable; however, they are generally of constant size, and thus, will normally not be significant in comparison to the size of more realistic (typically larger) C++ application programs.

Using UPX to Compress Executable Files

UPX (the Ultimate Packer for eXecutables) is a tool which, notwithstanding the avoidance of undesirable code generator overheads, as described above, compresses executable files to achieve further reduction of file size. It works for the executable file formats of several operating systems, including 32‑bit MS‑Windows, and is free for use with all  applications, (even those which are distributed commercially); it uses an efficient compression algorithm, producing compressed files which remain executable, and are rapidly decompressed in‑place,  when invoked.

For most effective size reduction, UPX may deployed using one  of the following invocations, (acting on the original uncompressedexample.exe):

C:\project> upx --brute example.exe
C:\project> upx --ultra-brute example.exe
C:\project> upx --best example.exe

to compress example.exe in‑place.  (Do note that, whereas the in‑place decompression  process can be performed quite rapidly, the compression  may require a considerably longer time; this is not generally a problem, since compression must be performed only once, for each newly generated executable file, whereas the relatively much quicker decompression must be repeated every time such a compressed executable file is run).