简体   繁体   English

静态函数和变量在共享库中导出

[英]Static function and variable get exported in shared library

So far I've assumed that objects with static linkage (ie static functions and static variables) in C do not collide with other objects (of static or external linkage) in other compilation units (ie .c files) so I've used "short" names for internal helper functions rather than prefixing everything with the library name. 到目前为止,我假设C中具有静态链接(即静态函数和静态变量)的对象不会与其他编译单元(即.c文件)中的其他对象(静态或外部链接)发生冲突,所以我使用了“简短的“内部帮助函数的名称,而不是使用库名称前缀所有内容。 Recently a user of my library experienced a crash due to a name collision with an exported function from another shared library. 最近,由于名称与另一个共享库中的导出函数发生冲突,我的库的用户遇到了崩溃。 On investigation it turned out that several of my static functions are part of the symbol table of the shared library. 经过调查,我发现我的几个静态函数是共享库的符号表的一部分。 Since it happens with several GCC major versions I assume I'm missing something (such a major bug would be noticed and fixed). 由于它发生在几个GCC主要版本中,我认为我缺少一些东西(这样一个主要的bug会被注意到并修复)。

I managed to get it down to the following minimum example: 我设法将其归结为以下最小示例:

#include <stdbool.h>
#include <stdlib.h>

bool ext_func_a(void *param_a, char const *param_b, void *param_c);
bool ext_func_b(void *param_a);

static bool bool_a, bool_b;

static void parse_bool_var(char *doc, char const *var_name, bool *var)
{
    char *var_obj = NULL;

    if (!ext_func_a(doc, var_name, &var_obj)) {
       return;
    }
    *var = ext_func_b(var_obj);
}

static void parse_config(void)
{
    char *root_obj = getenv("FOO");
    parse_bool_var(root_obj, "bool_a", &bool_a);
    parse_bool_var(root_obj, "bool_b", &bool_b);
}

void libexample_init(void)
{
    parse_config();
}

Both the static variable bool_a and the static function parse_bool_var are visible in the symbol table of the object file and the shared library: 静态变量bool_a和静态函数parse_bool_var都可以在目标文件和共享库的符号表中看到:

$ gcc -Wall -Wextra -std=c11 -O2 -fPIC -c -o example.o example.c
$ objdump -t example.o|egrep 'parse_bool|bool_a'
0000000000000000 l     O .bss   0000000000000001 bool_a
0000000000000000 l     F .text  0000000000000050 parse_bool_var
$ gcc -shared -Wl,-soname,libexample.so.1 -o libexample.so.1.1 x.o -fPIC 
$ nm libexample.so.1.1 |egrep 'parse_bool|bool_a'
0000000000200b79 b bool_a
0000000000000770 t parse_bool_var

I've dived into C11, Ulrich Drepper 's "How to Write Shared Libraries" and a couple of other sources explaining visibility of symbols, but I'm still at a loss. 我已经潜入C11, Ulrich Drepper的“如何编写共享库”以及其他几个解释符号可见性的来源,但我仍然不知所措。 Why are bool_a and parse_bool_var ending up in the dynamic symbol table even though they're declared static ? 为什么bool_aparse_bool_var在动态符号表中结束,即使它们被声明为static

The lower case letter in the second column of nm output means they're local (if they were upper case, it would be a different story). nm输出的第二列中的小写字母表示它们是本地的(如果它们是大写的,那么它将是一个不同的故事)。 Those symbols won't conflict with other symbols of the same name and AFAIK, are basically there only for debugging purposes. 这些符号不会与同名的其他符号和AFAIK冲突,基本上只用于调试目的。 Local symbols won't go into the dynamic symbol table (printable with nm -D but only in shared libraries) either and they are strip pable along with exported symbols (upper case letters in the second column of nm output) that aren't dynamic. 局部符号不会进入动态符号表(可以使用nm -D打印,但只能在共享库中打印)并且它们是strip pable以及非动态的导出符号( nm输出的第二列中的大写字母) 。

(As you will have learned from Drepper's How to Write Shared Libraries, you can control visibility with -fvisibility=(default|hidden) (shouldn't use protected) and with visibility attributes.) (正如您将从Drepper的如何编写共享库中学到的,您可以使用-fvisibility=(default|hidden) (不应使用受保护)和可见性属性来控制可见性。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM