tags:

views:

436

answers:

8

Hi,

I have a static library *.lib created using MSVC on windows. The size of library is say 70KB. Then I have an application which links this library. But now the size of the final executable (*.exe) is 29KB, less than the library. What i want to know is :

  1. Since the library is statically linked, I was thinking it should add directly to the executable size and the final exe size should be more than that? Does windows exe format also do some compression of the binary data?

  2. How is it for linux systems, that is how do sizes of library on linux (*.a/*.la file) relate with size of linux executable (*.out) ?

-AD

+2  A: 

The static library probably contains several functions which are never used. When the linker links the library with the main executable, it sees that certain functions are never used (and that their addresses are never taken and stored in function pointers), it just throws away the code. It can also do this recursively: if function A() is never called, and A() calls B(), but B() is never otherwise called, it can remove the code for both A() and B(). On Linux, the same thing happens.

Adam Rosenfield
It's not actually just the functions referenced, but them plus any symbols in the same *.o files (i.e., whole objects get thrown into the final output, not just functions), so if A and B are in the same .o as C, and C gets called, then they'll all be in there.
tgamblin
Not necessarily, only with dumb compilers/linkers.
MSalters
+6  A: 

A static library on both Windows and Unix is a collection of .obj/.o files. The linker looks at each of these object files and determines if it is needed for the program to link. If it isn't needed, then the object file won't get included in the final executable. This can lead to executables that are smaller then the library.

EDIT: As MSalters points out, on Windows the VC++ compiler now supports generating object files that enable function-level linking, e.g., see here. In fact, edit-and-continue requires this, since the edit-and-continue needs to be able to replace the smallest possible part of the executable.

David Norman
File-level linking is really a UNIX problem; for MSVC the norm has become function-level linking.
MSalters
A: 

Disclaimer: It's been a long time since I dealt with static linking, so take my answer with a grain of salt.

You wrote: I was thinking it should add directly to the executable size and final exe size should be more than that?

Naive linkers work exactly this way - back when I was doing hobby development for CP/M systems (a LONG time ago), this was a real problem.

Modern linkers are smarter, however - they only link in the functions referenced by the original code, or as required.

Bevan
It's not actually just the functions referenced, but them plus any symbols in the same *.o files (i.e., the .o file is the granularity of linking).
tgamblin
You're right - a detail I'd forgotten in the meantime. It's almost like software archeology!
Bevan
A: 

Thanks @David and @Adam:

But assuming i have made sure that there is no dead code or unused functions in my library, only those which will be called are kept to compile. Then how does one explain this?

-AD

goldenmean
A: 

Additionally to the current answers, the linker is allowed to remove function definitions if they have identical object code - this is intended to help reduce the bloating effects of templated code.

1800 INFORMATION
I don't think that's quite right: You're thinking of C++, I guess? The removal of duplicates should be based on the SIGNATURE of the function, (eg, the name, and the types of args) rather than on the object code. If you have two functions with different code but same signature, what happens...???
Roddy
No, actually I am thinking of the object code. The linker can remove a function if the generated object code is identical to that of another. You can see this in a debugger, for example, you can see stack traces for optimised code that has different functions than you would expect in it
1800 INFORMATION
+1  A: 

There is additional bookkeeping information in the .lib file that is not needed for the final executable. This information helps the linker find the code to actually link. Also, debug information may be stored in the .lib file but not in the .exe file (I don't recall where debug info is stored for objs in a lib file, it might be somewhere else).

Greg Hewgill
A: 

A static library has to contain every symbol defined in its source code, because it might get linked into an executable which needs just that specific symbol. But once it is linked into an executable, we know exactly which symbols end up being used, and which ones don't. So the linker can trivially remove unused code, trimming the file size by a lot. Similarly, any duplicate symbols (anything that's defined in both the static library and the executable it's linked into gets merged into a single instance.

jalf
A: 

@All: Thanks for the pointers. @Greg Hewgill - Your answer was a good pointer. Thanks.

The answer i found out was as follows:

1.)During Library building what happens is if the option "Keep Program debug databse" in MSVC (or something alike ) is ON, then library will have this debug info bloating its size. but when i statically include that library and create a executable, the linker strips all that debug info from the library before geenrating the exe and hence the exe size is less than that of the library.

2.) When i disabled the option "Keep Program debug databse", i got an library whose size was smaller than the final executable, which was what i thought is nromal in most situations.

-AD

goldenmean