   Reducing the executable size of a C++ App.
  Often, when programming large applications in C++, the executable tends to get huge (several megabytes). I know that some factors (C++ features) such as inline abuse, templates, constructors, strings, etc. contribute to adding fat to the binary executable. Although this isn't a big problem in desktop PCs, which have gigabytes of RAM nowadays, it is very serious when writing games for mobile or embedded devices. So my question is, are there any tools or profiling techniques to somehow "detect" which sections of a binary (functions, constants, , etc) are consuming the most space? I know that there are many memory, cpu, I/O profilers around, but executable binary size profiling seems not to be a common area of optimization...Please don't mention UPX, since the goal of this is to save RAM.
  dumpbin from MVS, objdump on other platforms. Quote:which sections of a binary (functions, constants, , etc)What kind of information is available depends on how the binary was linked. Non-debug executables have most of information stripped out.Usually one would examine the .obj/.o and similar intermediate files.   ;  At work we have a custom tool that parses out the .map files that visual studio generates. This lets us see code and data sizes from the executable.;  Reducing executable file size might be as simple as turning off the debug information. Check your compiler settings. Do you have a particular operating system in mind? Are you familiar with how virtual memory operates? Are you familiar with how your target operating system loads executable files?   ;  Like KulSeran says:  The best way that I know of to examine sizes is to generate and examine a 'map file' - this is basically a way of determining where functions, static data, and resources live in your executable file, and/or where they will be loaded at runtime.If you want to further analyze code, you need to examine the assembly instructions (an assembly listing file can be generated by many compilers at build time).You can also just open the EXE in a hex editor and see if there's any obviously wasted space (usually the only time this can be seen at a glance is for large static arrays which are initialized to zero).Some things that generally reduce code size for x86 programs are:- Set optimization settings as aggressive as possible, EXCEPT for loop unrolling, if you can adjust that separately.- Experimenting with function inlining settings.  Counterintuitively, sometimes turning it on will SAVE space.- Make sure dead code stripping is enabled.- Remove all debugging symbols.- Disable exceptions and RTTI.- If you use lots of templated containers, try to use the fewest amount of unique data types as possible in those containers.- Try the 'omit frame pointer' option - this skips the 'push ebp; mov ebp, esp' at the start of every function, saving you 3 bytes, and between 1 and 3 bytes at the end depending on whether the compiler uses the 'LEAVE' instruction or manually MOVs and pops EBP.  It also frees up the EBP register for general-purpose use as a 7th general purpose register, which can decrease the amount of memory or instructions needed when shuffling data around.- Compile in 32-bit rather than 64-bit mode unless you plan to perform LOTS of 64-bit integer math, or use more than 3GB of RAM.  64-bit instructions that use the REX prefix tend to be wasteful.- Avoid large static arrays if there is an alternative.- Change alignment and struct packing to eliminate padding wherever possible (this can result in speed issues or alignment exceptions depending on what you're doing).For RISC:- I've found that instruction sets with fixed size instructions (RISC 32-bit) tend to be EXTREMELY wasteful (in space) compared to x86's variable-width instructions.  You might be able to shrink your codebase by switching the majority of your code to use interpreted bytecode (WITHOUT JITting it).  This is a pretty extreme thing to do though, since it will destroy your performance.[Edited by - Nypyren on August 6, 2010 8:02:11 PM];  I've found the code size is often not a very big factor when you start seeing huge binaries.  Usually it's stuff like debug symbols (like previously mentioned) and large statically initialized arrays.  e.g. the following is inspired by a real-world example and compiles to 10MB on my machine even when optimized for size:#include <stdio.h>char ar[10000000] = {0};int main(){    printf("hello world\n");}Just taking out the "={0}" bit cuts it down to 9k.   ;Quote:Original post by Anon MikeI've found the code size is often not a very big factor when you start seeing huge binaries.  Usually it's stuff like debug symbols (like previously mentioned) and large statically initialized arrays.  e.g. the following is inspired by a real-world example and compiles to 10MB on my machine even when optimized for size:*** Source Snippet Removed ***Just taking out the "={0}" bit cuts it down to 9k.That also depends on the compiler you're using; when compiled using my GCC 4.5 with optimizations disabled, even without removing "={0}" it creates 4KB binary. (The array was most likely moved to the .bss section.)   ;Quote:Original post by Anon MikeI've found the code size is often not a very big factor when you start seeing huge binaries.  Usually it's stuff like debug symbols (like previously mentioned) and large statically initialized arrays.  e.g. the following is inspired by a real-world example and compiles to 10MB on my machine even when optimized for size:*** Source Snippet Removed ***Just taking out the "={0}" bit cuts it down to 9k.Yup. That was the example I was going to give too. When I ported my software 3D engine from VS6 to VS2005 some time ago, the size became about a megabyte larger until I made that exact change.   ;  I'll second (or third) the map file suggestion.Look at the final build's map file, study it, love it.* You can find large blocks of static data.  They generally indicate design flaws.* You can find functions that ought to be inlined but are not (generally anything under 50 or so bytes, but sometimes much larger).* You can find functions that ought to be de-inlined if you are thoughtful in your analysis.* You can find templates that may have exploded in size.* You can sometimes find dead code to stop maintaining.* You can (sometimes) track classes and objects that are larger than expected or desired.The map file can also help with runtime optimization.  Since you (ought to) understand cache effects, the sizes of functions and sizes of data ought to reveal some of the more obvious changes.Another useful item, assuming you have a continuous or nightly build system, is to have the build system track executable sizes.  Even better if you can track the size of each segment (code, data, bss ...) or the size by library or subsystem.  Graph it in excel and look for spikes.  Those usually indicate something that needs to be reviewed.   