Статическая функция и переменная экспортируются в общую библиотеку - PullRequest
0 голосов
/ 28 мая 2018

До сих пор я предполагал, что объекты со статической связью (то есть статическими функциями и статическими переменными) в C не сталкиваются с другими объектами (статической или внешней связью) в других единицах компиляции (то есть .c файлах), поэтому яиспользовал «короткие» имена для внутренних вспомогательных функций вместо того, чтобы ставить префикс перед именем библиотеки.Недавно у пользователя моей библиотеки произошел сбой из-за конфликта имен с экспортированной функцией из другой общей библиотеки.В ходе расследования выяснилось, что некоторые из моих статических функций являются частью таблицы символов разделяемой библиотеки.Так как это происходит с несколькими основными версиями GCC, я предполагаю, что я что-то упустил (такая серьезная ошибка была бы замечена и исправлена).

Мне удалось привести ее к следующему минимальному примеру:

#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();
}

И статическая переменная 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

Я погрузился в C11, Ульрих Дреппер"Как писать общие библиотеки" и несколько других источников, объясняющих видимость символов, но я все еще в замешательстве.Почему bool_a и parse_bool_var попадают в динамическую таблицу символов, даже если они объявлены static?

1 Ответ

0 голосов
/ 28 мая 2018

Строчная буква во втором столбце вывода nm означает, что они локальные (если бы они были в верхнем регистре, это была бы другая история).Эти символы не будут конфликтовать с другими символами с таким же именем и AFAIK, в основном там только для целей отладки.Локальные символы не попадут в таблицу динамических символов (печатается с nm -D, но только в общих библиотеках), и они могут strip записываться вместе с экспортированными символами (заглавными буквами во втором столбце вывода nm), которыене являются динамическими.

(Как вы узнали из Drepper's Как писать общие библиотеки, вы можете управлять видимостью с помощью -fvisibility=(default|hidden) (не следует использовать защищенный) и с атрибутами видимости.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...