Как компилятор (и компоновщик) Linux C ++ решает, куда поместить typeinfo? - PullRequest
3 голосов
/ 23 мая 2011

У меня есть класс, определенный в одном файле h и реализованный в cpp, который является частью одной библиотеки (назовем его libdef).

У меня есть две другие библиотеки, в которых есть файлы cpp, которые включают этотч файл.Один из них выполняет dynamic_cast () с этим классом (мы назовем его libdyn), а другой - с новым для этого класса (назовем его libnew).

Кажется, что в одной из этих библиотек естьtypeinfo для типа, но не для другого:

user@machine> ld --cref libdef.so | grep -E "typeinfo for MyClass"
ld: warning: cannot find entry symbol _start; not setting start address
typeinfo for MyClass libdef.so

user@machine> ld --cref libnew.so | grep -E "typeinfo for MyClass"
ld: warning: cannot find entry symbol _start; not setting start address
typeinfo for MyClass libdef.so

user@machine> ld --cref libdyn.so | grep -E "typeinfo for MyClass"
ld: warning: cannot find entry symbol _start; not setting start address
typeinfo for MyClass libdyn.so

Как вы можете видеть, libdef и libnew используют typeinfo из libdef, но libdyn использует свою собственную typeinfo.Это почему?Как компилятор / компоновщик решает, помещать typeinfo в одну библиотеку или ссылаться на нее из другой?

Я должен отметить, что и libnew, и libdyn созданы с помощью -llibdef.

user@machine> icpc -V
Intel(R) C++ Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 12.0.0.084 Build 20101006
Copyright (C) 1985-2010 Intel Corporation.  All rights reserved.

user@machine> ld -V
GNU ld version 2.17.50.0.6-14.el5 20061020
Supported emulations:
 elf_x86_64
 elf_i386
 i386linux

После некоторых проверок, которые я сделал, это зависит от того, «видят» ли cpp-файлы библиотеки определение виртуального метода или нет.

Этот код не приведет к тому, что символ typeinfo будет находиться в библиотеке:

class SomeClass { public: SomeClass(); virtual void func(); };

Этот код произведет символ typeinfo в библиотеке:

class SomeClass { public: SomeClass() {} virtual void func() {} };

Если он присутствует, символ typeinfo будет иметь неопределенную связь.

Ответы [ 4 ]

3 голосов
/ 23 мая 2011

G ++, вероятно, определяет typeinfo для класса как слабый символ, в каждом объектном файле, который нуждается в этом. Один из объекта файлам в libdef это нужно, потому что это часть vtable устанавливается конструктором. И один из объектных файлов в libdyn нужно, потому что dynamic_cast. Я упал libnew делает это новым, но, скорее всего, оно не понадобится (если конструктор не встроен). Во всяком случае, если это действительно является слабым символом, только одно из определений будет включены в финал или исполняемый файл; который из не указано (но я подозреваю, что это первый компоновщик встречает & mdash; что соответствует тому, что вы видите).

Ничто из этого не имеет значения в большинстве случаев. (Исключение составляет, если вы звоните dlopen с RTLD_LOCAL; сделай это, и dynamic_cast, скорее всего, потерпит неудачу, если выполняется в .so кроме того, что с конструктором объекта.)

2 голосов
/ 23 мая 2011

Как уже упоминалось, это зависит от реализации C ++. Но здесь - это описание того, как это делает g ++.

Вкратце, если возможно, g ++ определяет класс vtable и type_info в модуле перевода, который определяет первый не встроенный виртуальный член класса.

0 голосов
/ 23 мая 2011

Я не знаю подробностей реализации вашего компилятора и компоновщика, но, возможно, он достаточно умен, чтобы не включать typeinfo там, где он не нужен?

0 голосов
/ 23 мая 2011

Я думаю, что это будет деталь реализации компилятора.

Обычно (поскольку сама виртуальная таблица является деталью реализации), virtual table хранит указатель на type info, и я думаю, что там, где хранится typeinfo, - это детали реализации компилятора. Скорее всего, он хранит typeinfo в so, который объявляет класс.

...