I am working in a legacy code, and I am facing a strange problem. I have the executable file, and it uses a .so library called dbaccess.so.
I also have a lib called “lib_base”, and this lib is statically linked to both projects (dbaccess.so and the executable).
________
|lib_base|
|________|
/ \
/ statically \
/ linked \
______ / \ _____________
|my_app| | dbaccess.so |
|______| <---dinamically |_____________|
The problem is that, inside the “lib_base”, I have in a .cpp (misc.cpp) file a variable defined as
char apName[_MAX_FNAME];
And inside a .cpp (clientconn.cpp) in “dbaccess.so” I have:
extern char apName[_MAX_FNAME];
And I’ve noticed some strange behaviors in the code. It looks like the “extern” variable is confusing the definition of “apName” inside the my_app’s lib_base and the one inside dbaccess’ lib_base.
When debugging a dbaccess’ function with gdb, the following happens:
strcpy( apName, "test" );
printf( apName );
in the console, “test” is printed, but if I write the following line in gdb’s console after the strcpy:
print apName
It prints “apfile.ini”.
Do someone know if this problem is really related to the fact that “lib_base” is linked to both projects? Is there any compilation flag or something that could be passed when compiling the dbaccess.so to avoid this?
I am using linux and gcc as compiler.
If you define a variable in a .cpp file that should only be visible within that file you should use
static.If you want to share the value between the two lib_base then you shouldn’t statically link it twice – you’re getting duplicates of both the code and the data, which is both inefficient and confusing.
C++ has this thing called the One Definition Rule that says you can define the same thing as many times as you like (so you can include the same header file in multiple cpp files), and as long they are all defined the same, and it will Just Work. Basically this means that the linker is allowed to throw away duplicate objects and just keep one, at random. If you break the ODR the compiler will not know, and linker will probably not know, and then you get undefined behaviour.
In this case you’ve not broken the ODR, but you’ve linked the same thing into two different objects (your app, and the shared library), which is a different problem. The dynamic linker (that loads shared libraries at run time) doesn’t worry about any of that nonsense – all it does is connect undefined symbols in the app to their definitions in the library. Your apName in the main app is clearly not undefined, so the dynamic linker has nothing to do there, so there’s no undefined behaviour here.
Assuming that you didn’t want both instances of lib_base to share the definition of aPname then your application appears to be linked just fine (printf proves that), but GDB doesn’t perform well with ambiguous symbol names. When GDB looks up symbol names it doesn’t necessarily know where to look first, so you don’t get the one you expected.
Sometimes GDB can sort itself out if you first do
list main(or whatever) to set the context you want. Basically though, don’t duplicate code – the debugger won’t like it.If you must do this, check out the
symbol-tableandadd-symbol-tablecommands – you can choose to load only the symbols from one file or the other, and debug the bit you need.