символы в статической библиотеке иногда связываются с исполняемым файлом, иногда нет - PullRequest
0 голосов
/ 10 января 2019

У меня есть статическая библиотека, которая генерируется из многих файлов cpp на linux с использованием g ++. один заголовочный файл содержит класс, который реализует шаблон фабрики

псевдокод в заголовочном файле, как показано ниже

class Factory
{
public:
    static Factory& instance();
    Base * create(const std::string& name);
    template<class T>
      void register_class(const std::string& name);
}

template <class T>
class FactoryRegister
{
public:
    FactoryRegister(const std::string& name)
    {
       Factory::instance().register_class<T>(name);
    }
}
Файл

cpp для Factory имеет свои реализации. в другом файле cpp Derive.cpp есть класс, который я хочу зарегистрировать в Factory. и я определил глобальную переменную, чтобы сделать это. код как показано ниже

FactoryRegister<Derive> g_register_derive("derive");

все эти файлы скомпилированы в одну статическую библиотеку и связаны с одним исполняемым файлом.

Насколько я понимаю, поскольку на g_register_derive не ссылается ни один код, он не должен быть связан с исполняемым файлом, если не указана опция целого архива.

странная часть в том, что если я помещу g_register_derive в Derive.cpp, то это правда, что этот символ не связан с исполняемым файлом. но если я помещу g_register_derive в Factory.cpp, он будет связан с исполняемым файлом.

Я использовал nm для проверки результата, и есть также строка кодовых вызовов Factory::instance().create("Derive"), которая также может использоваться для проверки, связан ли g_register_derive или нет.

и, конечно, если я предоставил опцию «целый архив», g_register_derive всегда будет связан с исполняемым файлом.

1 Ответ

0 голосов
/ 10 января 2019

См. вики-тег Stackoverflow о статических библиотеках понять связь со статическими библиотеками, особенно тот факт, что по умолчанию объектный файл libx.a(p.o) в статической библиотеке извлекается и связывается с программой только в том случае, если компоновщик нуждается в .

Если компоновщик должен связать участника архива libx.a(p.o), чтобы разрешить некоторую предварительную ссылку на символ foo, который определен в этом объектном файле, тогда определение любого другого символа bar, который также определен в libx.a(p.o) также связан с программой - потому что он является частью этого объектного файла - будь то bar указана программой или нет.

Итак, если вы определите g_register_derive в исходном файле p.cpp, который скомпилирован на p.o и заархивирован как libx.a(p.o), и ваше приложение должно быть связано libx.a(p.o) по любой причине , тогда по умолчанию 1 g_register_derive становится определено в вашей программе.

Если вы переместите определение g_register_derive в q.cpp, который компилируется и архивируется как libx.a(q.o), и ваше приложение не нужно связать libx.a(q.o) по любой причине, тогда g_register_derive не определено в вашей программе.


[1] С опциями компиляции и компоновки не по умолчанию вы можете удалить определения неиспользованных символов из вашей программы. См. Как удалить неиспользуемые символы C / C ++ с помощью GCC и ld? и принятый ответ.

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