2016-12-27 11 views
3

У меня есть 2 CPP файлы, каждый из которых объявлено 1 класса +-функция + 1 статического объекта:Тот же код на C++, другая опция ссылки приводит к разному поведению?

$ cat mya.cpp 
#include<stdio.h> 
struct A{ 
    A(){printf("%s\n",__FUNCTION__);} 
}; 
void fa(){printf("%s\n",__FUNCTION__);} 
static A s_obj; 

$ cat myb.cpp 
#include<stdio.h> 
struct B{ 
    B(){printf("%s\n",__FUNCTION__);} 
}; 
void fb(){printf("%s\n",__FUNCTION__);} 
static B s_obj; 

Тогда главная функция называет "FB", но не "ФА".

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

Я попытался собрать и связать эти файлы разными способами:

g++ -c mya.cpp -fPIC 
g++ -c myb.cpp -fPIC 
ar -rvs libmya.a mya.o 
ar -rvs libmyb.a myb.o 
ar -rvs libmystatic.a mya.o myb.o 
g++ --shared -o libmyshare.so mya.o myb.o 
g++ --shared -o libadyn.so mya.o 
g++ --shared -o libbdyn.so myb.o 
g++ nm.cpp -o use1StaticLib -lmystatic -L. 
g++ nm.cpp -o use2StaticLib -lmyb -lmya -L. 
g++ nm.cpp -o use1DynamicLib -lmyshare -L. 
g++ nm.cpp -o use2DynamicLib -ladyn -lbdyn -L. 
g++ nm.cpp -o useDirect mya.cpp myb.cpp 

Тогда я нашел 5 исполняемые файлы имеют различное поведение:

$ ./useDirect 
A 
B 
fb 

$ ./use1DynamicLib 
A 
B 
fb 

$ ./use2DynamicLib 
B 
fb 

$ ./use1StaticLib 
A 
B 
fb 

$ ./use2StaticLib 
B 
fb 

Тот же код, другое поведение, как я не могу смутить?

Кажется, я нашел какую-то подсказку, если mya.cpp и myb.cpp упакованы в другой файл .a/.so, тогда «A s_obj» не сконструирован. Зачем? Конструктор A имеет побочный эффект, и я не указываю никакой оптимизации -O.

Если причина в том, что «A_obj» - это объект, который не используется, поэтому не связан, то «B s_obj» не используется основной функцией, почему она всегда построена?

Нужно слышать объяснения ваших экспертов!

+0

На глобальных конструкторов нельзя полагаться, но вы уже это знали. Это просто неопределенно, вероятно, так как есть как язык, так и правила os. – Jojje

ответ

2

Я думаю, что есть 2 здесь эффекты, которые нужны, чтобы быть отличать

Во-первых, когда вы делаете звонки на внешние библиотеки, динамический компоновщик ленив и только библиотеки нагрузки, которые на самом деле называются. Но он загрузит всю библиотеку. С use2StaticLib вы используете только lib b, чтобы он загружал только этот. То же самое относится и к use2DynamicLib

Во-вторых, это пишу:

g++ --shared -o libmyshare.so mya.o myb.o

такая же, как с помощью

g++ --shared -o libmyshare.so myfile.o

где myfile.cpp является конкатенация mya.cpp и myb.cpp Вы просто копируя два объектных файла в более крупный libmyshare.so, поэтому, когда вы вызываете одну функцию из myb.cpp файл, приложение загружает всю библиотеку libmyshare.so. Затем конструкторы A и B вызывают в этом случае инициализацию статических объектов. Это не меняет, является ли компиляция libmyshare.so статической или динамической.

В любом из этих сценариев код libA и libB включен в ваш код приложения (даже при компиляции статически), и все библиотеки вызывают динамическое связывание.

Надеюсь, что эта помощь!

 Смежные вопросы

  • Нет связанных вопросов^_^