2016-12-28 17 views
3

Я ожидал, что:C++ отличается между ссылкой на .o и с .a файлом: по-разному, почему?

связь с .o файла, и связь с .a файла Архивировано из файла .o, не должно быть никакой разницы.

Но факт не факт. У меня 2 исходных файлов, каждый из которых декларирование 1class + 1 статический объект + 1 функция, и main.cpp, что называется одна из функций

$cat First.cpp 
#include<stdio.h> 
struct First{ 
    First(){printf("First\n");} 
}; 
void f1(){printf("f1\n");}//Not called in main 
static First f_obj; 

$cat Second.cpp 
#include<stdio.h> 
struct Second{ 
    Second(){printf("Second\n");} 
}; 
void f2(){printf("f2\n");}//Not called in main 
static Second s_obj; 

$cat main.cpp 
void f2(); 
int main() 
{ 
    f2(); 
    return 0; 
} 

$g++ -c First.cpp -fPIC 
$g++ -c Second.cpp -fPIC 
$ar -rvs libmystatic.a First.o Second.o 
$g++ main.cpp -o MylinkSta -lmystatic -L. 
$g++ main.cpp -o MyDirect First.o Second.o 

$./MylinkSta 
Second 
f2 

$./MyDirect 
Second 
First 
f2 

Таким образом, вы можете увидеть

(1) текущий результат MylinkSta не создает объект «First», но MyDirect делает.

(2) Пока объект «Второй» всегда построен.

Я действительно не вижу разницы между ссылкой на 2 '.o' файлы и ссылкой на файл .a, который заархивирован из этих 2'.o 'файлов.

Почему они ведут себя по-другому? Я экспериментировал с gcc/clang на rhel/ubuntu, все показывают тот же результат. Интересно, существует ли какой-либо стандарт C++ ABI, который говорит, когда должен быть действительно вызван статический/глобальный объект, любым способом связывания?

Как происходит эта разница?

+0

Линкером будут использоваться только объектные файлы из библиотеки, которые действительно необходимы для удовлетворения некоторой внешней ссылки; те, на которые не ссылаются никоим образом, игнорируются, глобальные переменные и все. Вы хотите это чаще всего - большая статическая библиотека обычно содержит больше кода, чем требуется для данной программы, вы бы не хотели, чтобы все это было связано с вашим исполняемым файлом, поэтому оно заканчивается тем, что содержит много мертвого, никогда не используемого кода. –

ответ

2

Это связано с семантикой статических библиотек. Linker будет включать только файлы из статической библиотеки, если он содержит символ, на который ссылается какой-либо файл объекта, который предшествует ему в командной строке (например, main.cpp ссылки f2 из Second, поэтому он включен). Вы можете переопределить это поведение с вашей библиотекой с помощью

-Wl,--whole-archive -lmystatic -Wl,--no-whole-archive 

но это не стандарт.

+0

Бинго, это вариант, который я искал для подачи «ld», он работал, чтобы явно связываться со всем. – Troskyvs