views:

1850

answers:

11

Hello,

I just recently started learning C++ - I am using nuwen's version of MingW on Windows, using NetBeans as an IDE (I have also MSDN AA Version of MSVC 2008, though I don't use it very often).

When compiling this simple program:

#include <iostream>
using namespace std;

int dog, cat, bird, fish;

void f(int pet) {
  cout << "pet id number: " << pet << endl;
}

int main() {
  int i, j, k;
  cout << "f(): " << (long)&f << endl;
  cout << "dog: " << (long)&dog << endl;
  cout << "cat: " << (long)&cat << endl;
  cout << "bird: " << (long)&bird << endl;
  cout << "fish: " << (long)&fish << endl;
  cout << "i: " << (long)&i << endl;
  cout << "j: " << (long)&j << endl;
  cout << "k: " << (long)&k << endl;
} ///:~

my executable was about 1MB big. When I changed project configuration from Debug to Release, used -O1 -Os flags ( stripping debugging symbols along the way ), binary size was reduced from 1MB to 544KB.

I am not a "size freak", but I am just wondering - is there any way, that I could reduce .exe size even more? I just think, that 544KB is just too much for such a simple application ).

+4  A: 

Not sure how much use it will be to you, but someone has done quite a lot of work on reducing the size of a simple Windows .exe.

They were able to create a simple .exe that will execute on a modern version of Windows in 133 bytes, by using some very extreme methods.

Colin Pickard
Maybe not directly related with his question, but thanks a lot for sharing your find!
merkuro
Equivalent exercise for Linux ELF files: http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html
Adam Rosenfield
+4  A: 

You get the C++ standard library, and other stuff I guess, statically linked in as mingw has its own implementation of these libraries.

Don't worry so much about it, when you make more complex program, the size won't grow accordingly.

nos
+1  A: 

Well when you use C++ standard library, exe can get big really quickly. If after stripping debug symbol, you still want to reduce the size of your software, you can use a packer like UPX. But, be warned, some antivirus choke on exe packed with UPX as some virus used it a long time ago.

Raoul Supercopter
+1  A: 

You could always run UPX on your exe after you have created it.

SteveL
+6  A: 

The

#include <iostream>

causes a lot of the standard library to be linked in, at least with g++. If you are really concerned about executable size, try replacing all uses of iostreams with printf or similar. This will typically give you a smaller, faster executable (I got yours down to about 6K) at the cost of convenience and type-safety.

anon
A: 

The major part of the size stems from the use of fairly extensive runtime libraries. So in real life you are actually linking a very large piece of 'dead code' if you have such a simple application.

As far as I know there are no linker flags to skip the unused parts of a linked library.

There are two ways I know of to fake a smaller application:

  1. Use dynamic linking. Then your application refers to the dynamically loaded library. You still need the full size (actually more) but you have a much smaller executable.
  2. Use an executable compression system.
Niels Basjes
+1  A: 

Basically, there's not really anything you can do to reduce that .exe size with a base distribution of mingw. 550kb is about as small as you can get it, because mingw and gcc/g++ in general are bad at stripping unused functions. About 530kb of that is from the msvcrt.a library.

If you really wanted to get into it, you might be able to rebuild the msvcrt.a library with -ffunction-sections -fdata-sections compiler options, and then use the -Wl,--gc-sections linker options when linking your app, and this should be able to strip a lot of that stuff out of there. But if you're just learning C++, rebuilding that library may be a bit advanced.

Or you could just use MSVC, which is great at stripping unused functions. That same bit of code compiled with MSVC produces a 10kb exe.

Gerald
+1  A: 

I replicated your test using Cygwin and g++. Your code compiled to 480k with -O2. Running strip on the executable reduced it to 280k.

In general, though, I suspect your problem is the use of the <iostream> header. This causes a fairly large library to be linked in. Also, note that cout << x does a lot more than just printing. There are locales and streams and all sorts of under-the-hood stuff.

If however, having a small executable size is a real, mission-critical objective, then avoid it and use printf or puts. If it's not, then I would say pay the one-time cost of iostream and be done with it.

Kaz Dragon
+3  A: 

You could use -s, which I believe is built into mingw as well. A simple hello world application compiled using g++ 3.4.4 on cygwin produced executable that was 476872 bytes, compiling again with -s (strips unnecessary data), reduced the same executable to 276480 bytes.

The same hello world application on cygwin using g++ 4.3.2 produced an executable of 16495 bytes, using strip reduced the size to 4608 bytes. As far as I can see, probably best to use more recent version of g++.

MingW has just released gcc 4.4.0, so if the executable size is important then I'd consider using that. As it indicates -s will probably help strip much of the debugging information out for you, that is only recommended if it is for production use.

Randai
Did you actually try out your example of using std::cout instead? I don't think that has any effect at all on the final exe, it just means that you can type a shorter name in the source.
Dolphin
@Dolphin @Max LybbertThanks for the information guys.
Randai
A: 

If you use the "nm" utility or some other program that shows whats in your .exe, you'll see that it contains tons of classes that someone might want to use, but that you don't.

Mike Dunlavey
+1  A: 

How is it that other compilers like msvc8 or even an order compiler like borland c++ 5.5.1 are capable of producing very small executables but mingw gcc isn't able to?

I did a quick compile of a 'hello world' for each of the following toolsets and observed the compiled executable size. Please note that in all these cases the runtime library is statically linked and all debug symbols have been stripped:

compiler toolchain           exe size                       exe size
                                 (w/iostream header)        (w/cstdio printf)
-------------------------------------------------------------------------
Borland C++ 5.5.1                 110kbyte                  52kbyte
MSVC 2008 express ed          102kbyte                      55kbyte
MinGW- GCC 3.4.5                  277kbyte                      <10kbyte
MinGW- GCC 4.4.1                  468kbyte                  <10kbyte

What's interesting is the later version of gcc 4.4.1 produces an even larger executable than gcc3.4.5, probably due to different version of libstdc++.

So is there really no way to remove dead code during the linking phase for mingw?

Victor T.