C++ linker issues

2019-08-12 01:49发布

问题:

I have this:

a.cpp

int localfunction () { return 1; }
int local_symbol = localfunction();

b.cpp

void thirdfunction () {};

main.cpp

void main () { thirdfunction (); }

When I compile this in a main executable everything works (even with optimizations), and the localfunction is executed at startup even if I don't call it directly.

Now, in Visual C++ and GCC , I put a.cpp and b.cpp in a static library (.lib). localfunction is no more executed/defined.

From what I understand the symbol is detected as "not used" and it is removed. But it sounds weird because:

  • Why it is not removed when I don't use the .lib file?
  • Since the lib is linked in, why the linker blows away the initialization code?

What I'm trying to do to is to have a set of startup function in every .lib file I use that register automatically some data. The main executable should not know what files are linked in nor explicitly reference "localfunction" (/INCLUDE does works but it is not optimal)

BTW : using the various VC++ options (OPT:NOREF , etc..) doesn't solve the problem.

Thank you! QbProg

回答1:

A static library is - basically - an library, or archive, of object files compiled from that library's constituent source files.

When the linker uses a static library to resolve dependencies while building an application, it follows a process of looking for object files in the library that help it resolve any undefined symbols in the program. It doesn't automatically include all of the object files in a library.

In your instance the object file generated from main.cpp refers to third_function(). This dependency can be resolved by linking in the object file generated from b.cpp. This object file introduces no further undefined symbols, so the linker can (and does) stop here.

Oh, and for maximum portability main should return int.



回答2:

When using gcc and needing a startup function which runs "automatically" before main() runs, I would just use __attribute__((constructor)).

Perhaps there is a similar way (pragma?) to define a function in VC++, then you could do some preprocessor macro magic to have a common way to declare those startup functions.



回答3:

Your linker will takes steps to reduce the executable size. It will determine that your exe does not use the 'said' function and not include it in its final generated code. Though it also depends on what optimization you're using in your project.

Instead if you wish to dynamically do this, the better alternative is to use LoadLibrary and create a DLL that all your programs can load and dynamically load the function and register what you need.



回答4:

You have to remeber the old days where size was a premium.

You have a massive maths library with 10,000 different functions. Now your application uses sin() and you link against libm.a (or -lm).

You definitely do not want to blat your application with 9,999 functions you do not use. So when using static libs it only pulls from the library exactly what is used (nothing more).

On the other hand shared libs are designed so that the whole thing is pulled into memory. Also (though it is not defined in any standard) most dynamic loaders will also run any static initialization code as they are loaded. (Note if you link against them they are generally loaded at application startup).