Easy check for unresolved characters in shared libraries?

I am writing a fairly large library of C ++ shared objects and ran into a small problem that debugs the pain:

If I define a function / method in the header file and forget to create a stub for it (during development), since I create as a general library of objects, and not an executable file, when compiling there are no errors, I forgot to implement this function. The only way to find out that something is wrong is the runtime when the application associated with this library crashes with an "undefined" error.

I'm looking for an easy way to check if I have all the characters I need at compile time, maybe something that I can add to my Makefile.

One solution that I came up with is to run the compiled library via nm -C -U to get a list of all undefined references. The problem is also that the list of all links is contained in other libraries, such as GLibC, which, of course, will be linked to this library when the final application is merged. One could use nm to grep output through all my header files and see if any of the names match .. but that seems insane. Surely this is not an unusual problem, and is there a better way to solve it?

+60
c ++ linker shared-libraries
Oct 24 '09 at 7:35
source share
4 answers

Check the linker option -z defs / --no-undefined . When creating a shared object, this will lead to communication failure if there are unresolved characters.

If you use gcc to invoke the linker, you will use the -Wl compiler -Wl to pass the option to the linker:

 gcc -shared ... -Wl,-z,defs 

As an example, consider the following file:

 #include <stdio.h> void forgot_to_define(FILE *fp); void doit(const char *filename) { FILE *fp = fopen(filename, "r"); if (fp != NULL) { forgot_to_define(fp); fclose(fp); } } 

Now, if you create this in a shared object, it will succeed:

 > gcc -shared -fPIC -o libsilly.so silly.c && echo succeeded || echo failed succeeded 

But if you add -z defs , the link will not work and will tell you about your missing character:

 > gcc -shared -fPIC -o libsilly.so silly.c -Wl,-z,defs && echo succeeded || echo failed /tmp/cccIwwbn.o: In function `doit': silly.c:(.text+0x2c): undefined reference to `forgot_to_define' collect2: ld returned 1 exit status failed 
+69
Nov 04 '09 at 1:25
source share

On Linux (which you seem to be using) ldd -r a.out should give you exactly the answer you are looking for.

UPDATE: a trivial way to create a.out , with which you can check:

  echo "int main() { return 0; }" | g++ -xc++ - ./libMySharedLib.so ldd -r ./a.out 
+8
Oct. 27 '09 at 6:23
source share

How about testuite? You create mock executable files that reference the characters you need. If the connection fails, it means that your library interface is incomplete.

+7
Oct 24 '09 at 7:41
source share

I had the same problem. I was developing a component model in C ++, and, of course, the components should load dynamically at runtime. Three solutions that I used come to mind:

  • Take some time to identify a build system that can build statically. You will lose some time developing it, but it will save you a lot of time by catching these annoying runtime errors.
  • Group your functions in well-known and understandable sections so that you can group functions / stubs to make sure that each corresponding function has its own stub. If you document this well, you can probably write a script that checks the definitions (through, for example, its comments on doxygen) and checks the corresponding .cpp file for it.
  • Make several test executables loading the same set of libraries and specify the RTLD_NOW flag for dlopen (if you are under * NIX). They will signal missing characters.

Hope this helps.

+3
Oct 24 '09 at 11:52
source share



All Articles