最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c - Duplicate global variables when using static library in shared library - Stack Overflow

programmeradmin4浏览0评论

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?

Share Improve this question asked Feb 14 at 19:20 user607722user607722 1,6762 gold badges13 silver badges22 bronze badges 3
  • soo call it void f() { void (*otherf)() = dlsym(handle, "f"); otherf(); }? – KamilCuk Commented Feb 14 at 19:23
  • 1 Good practice is to use unique and meaningful names. Using single-letter variable names except inthe most immediate context is a terrible practice. – Weather Vane Commented Feb 14 at 19:23
  • Possible, in platform-dependent ways, but doesn't worth it. Put your f into another shared object. – Lorinczy Zsigmond Commented Feb 15 at 9:32
Add a comment  | 

1 Answer 1

Reset to default 4

Wonder 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 the RTLD_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
发布评论

评论列表(0)

  1. 暂无评论