[C/C++] линковка траблз
> которая оказалось в том же модуле трансляции, что и
> действительно используемая функция.
> Является ли это поведение правильным для линкера?
Да. Он знает только то, что ему надо подправить такое-то место
в двоичном коде, а используется ли соответствующий код или нет,
определить уже невозможно.
> Ведь если переместить код func_with_external_use в другой
> объектный файл и собрать ту же библиотеку, то проблемы не будет.
Так и надо делать.
---
"Vyroba umelych lidi, slecno, je tovarni tajemstvi."
это по дефолту делается и в студии и в gcc
для предотвращения этого эффекта
1) режут .cpp на части
2) используют магический ключик для линкера (скорее всего такая оптимизация есть для линкеров, но она не дешевая в плане производительности и я не знаю ключик)
есть еще ключик (в gcc точно чтобы при линковке с lib брались в бинарь _все_ obj из этой либины. такой гремучий бинарь получается
а используется ли соответствующий код или нет,Мне проще согласиться с 'ом, что это возможно, но дорого. Потому что я не понимаю, почему это может быть невозможно. Есть точка входа в программу, можно раскрутить всевозможные вызовы и составить точный их список.
определить уже невозможно
Однако, спасибо за ответ. Придется разделять. Странно, я думал линкеры по умолчанию умнее.
Он написал то же самое, только другими словами.
> что это возможно, но дорого.
Ну, если ты сможешь правильно порезать секцию, то вперёд.
Кстати, если настолько не хочется резать файлы, тогда подсунь
файл, определяющий недостающие символы:
int uuid_generate;
---
"Narrowness of experience leads to narrowness of imagination."
Но сложности будут, например, в таком случае:
registration.h:
void register( void (*f const char* name );
void callByName( const char* name );
registration.cpp:
// implement register and callByName using map or something
Registrar.h:
#include "registration.h"
class Registrar {
public:
Registrar( void (*f const char* name ) {
register( f, name );
}
};
aux.cpp:
void g { ... }
Registrar g_registrar( g, "A cool func" );
main.cpp
#include "registration.h"
int main
{
call_by_name( "A cool func" );
}
Понятно, что пример не минимальный (хотя и отброшены для простоты
тут очень надо, чтобы aux.o обязательно-обязательно был влинкован, иначе что-то не заработает.
Ведь в C++ большинство мыслей типа «а забацаем-ка мы вот такой крутой статический анализ кода» обламывается именно из-за того, что можно спрятать указатель в заднем кармане.
тут очень надо, чтобы aux.o обязательно-обязательно был влинкован, иначе что-то не заработает.А какие есть поводы его отбросить? В нем объявляется переменная и вызывается ее конструктор,
Хотя это тоже для меня загадка, все ли глобальные переменные из разных модулей подключаются или может быть так, что линкер решит модуль не использовать, и переменная не будет создана. Наверное это где-то четко описано, но я не знаю.
А какие есть поводы его отбросить? В нем объявляется переменная и вызывается ее конструктор,отбрасывал ld, иначе бы этой истории и не было.
Но сейчас подумал, действительно, пожалуй это бага (отрубание конструктора влияет на семантику надо зачекать в новых версиях.
Забавно, что нужная функциональность уже есть: -ffunction-sections в gcc и --gc-sections в ld. В студийном компиляторе, вроде бы, есть аналог.
Вообще, надо попробовать, какой профит в зависимости от соотношения используемых/неиспользуемых функций в либе. Есть такая статистика?
Финальная линковка сливает все секции, оверхед наблюдается только во время билда
Круто, спасибо.
Оставить комментарий
erotic
Объясните пожалуйста, согласуется ли это с какими-либо общечеловеческими нормами, или ошибка линкера?Есть библиотека с двумя функциями и один файл с реализацией этих функций:
lib.h
lib.c
Тут uuid_generate находится во внешней библиотеке libuuid, но это не играет особой роли - главное, что вызывается функция из другой библиотеки.
Собрал статически библиотеку, теперь собираю программу:
main.c:
Поскольку я использую только функцию func, я надеюсь, что мне достаточно слинковать программу только с моей liblib.a. Но
Т.е. линкер пытается найти зависимости для неиспользуемой функции, которая оказалось в том же модуле трансляции, что и действительно используемая функция.
Является ли это поведение правильным для линкера?
Ведь если переместить код func_with_external_use в другой объектный файл и собрать ту же библиотеку, то проблемы не будет.
В случае сборки шареной библиотеки не собирается ни в какой комбинации, это тоже меня удивляет.
Та же фигня в gcc 4.1.2, в студии пока не пробовал собирать.