Say I have a function f() in static library that simply prints how many times it is called.
#include<stdio.h>
int a = 0;
void f() {
printf("f at %p was invoked %d times\n", &f, ++a);
}
It is used in a shared library
#include <stdio.h>
void f();
void hello() {
f();
}
Both functions f() and hello() are invoked from main program.
#include <stdio.h>
#include <dlfcn.h>
void f();
int main() {
void *handle = dlopen("./libdynamic.so", RTLD_LAZY);
if (!handle) {
fprintf(stderr, "%s\n", dlerror());
return 1;
}
void (*hello)() = dlsym(handle, "hello");
char *error;
if ((error = dlerror()) != NULL) {
fprintf(stderr, "%s\n", error);
return 1;
}
hello();
hello();
f();
f();
dlclose(handle);
return 0;
}
makefile
all:
gcc -c -fPIC static.c -o static.o
gcc -shared -fPIC dynamic.c static.o -o libdynamic.so
gcc main.c -o main static.o
I am getting
f at 0x7f7e0fd4213e was invoked 1 times
f at 0x7f7e0fd4213e was invoked 2 times
f at 0x55e19d9722d4 was invoked 1 times
f at 0x55e19d9722d4 was invoked 2 times
There are 2 copies of f
and global var a
, one linked to shared library, one linked to main.
Wonder is it possible to have the shared library share the same global var a
and f
as main program?
Have anyone running into similar problem in practice? What's the best practice?
Say I have a function f() in static library that simply prints how many times it is called.
#include<stdio.h>
int a = 0;
void f() {
printf("f at %p was invoked %d times\n", &f, ++a);
}
It is used in a shared library
#include <stdio.h>
void f();
void hello() {
f();
}
Both functions f() and hello() are invoked from main program.
#include <stdio.h>
#include <dlfcn.h>
void f();
int main() {
void *handle = dlopen("./libdynamic.so", RTLD_LAZY);
if (!handle) {
fprintf(stderr, "%s\n", dlerror());
return 1;
}
void (*hello)() = dlsym(handle, "hello");
char *error;
if ((error = dlerror()) != NULL) {
fprintf(stderr, "%s\n", error);
return 1;
}
hello();
hello();
f();
f();
dlclose(handle);
return 0;
}
makefile
all:
gcc -c -fPIC static.c -o static.o
gcc -shared -fPIC dynamic.c static.o -o libdynamic.so
gcc main.c -o main static.o
I am getting
f at 0x7f7e0fd4213e was invoked 1 times
f at 0x7f7e0fd4213e was invoked 2 times
f at 0x55e19d9722d4 was invoked 1 times
f at 0x55e19d9722d4 was invoked 2 times
There are 2 copies of f
and global var a
, one linked to shared library, one linked to main.
Wonder is it possible to have the shared library share the same global var a
and f
as main program?
Have anyone running into similar problem in practice? What's the best practice?
1 Answer
Reset to default 4Wonder is it possible to have the shared library share the same global var a and f as main program?
Shared libraries behave differently on different systems. The details of how a shared library was built and how the main executable was built may also have an effect.
Your examples feel Linux-ish. On GNU / Linux:
You can observe that The Linux documentation for dlopen()
says:
Symbol references in the shared object are resolved using (in order): symbols in the link map of objects loaded for the main program and its dependencies; symbols in shared objects (and their dependencies) that were previously opened with
dlopen()
using theRTLD_GLOBAL
flag; and definitions in the shared object itself (and any dependencies that were loaded for that object).Any global symbols in the executable that were placed into its dynamic symbol table by ld(1) can also be used to resolve references in a dynamically loaded shared object. Symbols may be placed in the dynamic symbol table either because the executable was linked with the flag "-rdynamic" (or, synonymously, "--export-dynamic"), which causes all of the executable's global symbols to be placed in the dynamic symbol table, or because ld(1) noted a dependency on a symbol in another object during static linking.
Note especially the last bit. If you want your dlopen()
'd shared library to be able to see the symbols from the main executable, then you will want to link the executable with the --export-dynamic
option, or else to give the linker a specific list of symbols to ensure are exported via the linker's --dynamic-list
option. In this case, that is not only necessary but also sufficient to make references to a
and f
in the shared library resolve to the copies from the main executable:
$ gcc -c -fPIC static.c -o static.o
$ gcc -shared -fPIC dynamic.c static.o -o libdynamic.so
$ gcc -Wl,--export-dynamic main.c static.o -o main -ldl
$ ./main
f at 0x401249 was invoked 1 times
f at 0x401249 was invoked 2 times
f at 0x401249 was invoked 3 times
f at 0x401249 was invoked 4 times
void f() { void (*otherf)() = dlsym(handle, "f"); otherf(); }
? – KamilCuk Commented Feb 14 at 19:23f
into another shared object. – Lorinczy Zsigmond Commented Feb 15 at 9:32