Trying to test a simple case where a global variable defined in a shared library is set by a program and used by the shared library, I saw a strange problem. Here are the program codes.
bar.cpp
#include <stdint.h>
#include <stdio.h>
extern "C" {
uint64_t var_from_lib;
}
class BC;
class BC {
public:
void bar(void);
BC();
~BC();
};
BC::BC()
{
}
BC::~BC()
{
}
void BC::bar(void)
{
printf("class function : var_from_lib = %lx\n", var_from_lib);
}
extern "C" {
void bar(void)
{
printf("global function : var_from_lib = %lx\n", var_from_lib);
BC tmp;
tmp.bar();
}
}
main1.c
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
extern uint64_t var_from_lib;
int main1(void)
{
void * dlh = dlopen("./libbar.so", RTLD_NOW);
if (!dlh) {
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
void (*bar)(void) = dlsym(dlh,"bar");
if (!bar) {
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
var_from_lib = 0x12341111;
bar();
return 0;
}
main2.c
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
extern uint64_t var_from_lib;
int main2(void)
{
void * dlh = dlopen("./libbar.so", RTLD_NOW);
if (!dlh) {
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
void (*bar)(void) = dlsym(dlh,"bar");
if (!bar) {
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
var_from_lib = 0x12342222;
bar();
return 0;
}
main.c
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
extern uint64_t var_from_lib; // = 0x12345678;
uint64_t __attribute__((weak)) var_from_lib; // = 0x12345678;
extern int main1();
extern int main2();
int main(int argc, char *argv[])
{
if (atoi(argv[1]) == 1) {
main1();
}
else if (atoi(argv[1]) == 2) {
main2();
}
else {
printf("usage : main [1|2]\n");
}
return 0;
}
Makefile
.PHONY: all clean test
LDEXTRAFLAGS ?=
all: prog
%.o: %.c
gcc -c -Wall -fpic -g -o $@ -ldl $<
%.o: %.cpp
g++ -c -Wall -fpic -g -o $@ $<
libbar.so: bar.o
g++ -shared -o $@ $<
prog: main.o main1.o main2.o | libbar.so
gcc $(LDEXTRAFLAGS) -o $@ $^ -ldl
clean:
rm -f *.o *.so prog
And here is the build and execution result which is different from what I thought.
ckim@ckim-ubuntu:~/testdir$ make
gcc -c -Wall -fpic -g -o main.o -ldl main.c
gcc -c -Wall -fpic -g -o main1.o -ldl main1.c
gcc -c -Wall -fpic -g -o main2.o -ldl main2.c
g++ -c -Wall -fpic -g -o bar.o bar.cpp
g++ -shared -o libbar.so bar.o
gcc -o prog main.o main1.o main2.o -ldl
ckim@ckim-ubuntu:~/testdir$ prog 1
global function : var_from_lib = 0
class function : var_from_lib = 0
The main1() changes the var_from_lib to 0x12341111 and main2() changes the variable to 0x12342222. I expected the changed values will be observed from inside the shared library but it is not!
I used debugger and checked the address of var_from_lib and it was the same seen from main.c and seen from bar.cpp. What could be wrong here?
Looks like you are not linking to the shared library. You are dlopen-ing it.
Your expected behavior works like this only when you are directly linking with the shared library.
With dlopen you are expected to do all the work yourself: using dlsym to obtain the address of a symbol that's defined by the shared library.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With