Защо библиотеката по време на изпълнение е опция за компилатор, а не опция за свързване?

Опитвам се да създам C/C++ статична библиотека с помощта на Visual Studio 2005. Тъй като изборът на библиотеката за изпълнение е опция за компилиране, аз съм принуден да създам четири варианта на моята библиотека, по един за всеки вариант на библиотеката за изпълнение:

  • /MT - статична библиотека за изпълнение
  • /MD - библиотека за изпълнение на DLL
  • /MTd - отстраняване на грешки в статична библиотека по време на изпълнение
  • /MDd - отстраняване на грешки DLL библиотека за изпълнение

Това са опции на компилатора, а не опции за свързване. Идвайки от фона на Linux, това изглежда странно. Различните библиотеки по време на изпълнение имат ли различни конвенции за извикване или нещо подобно? Защо различните библиотеки по време на изпълнение не могат да бъдат разрешени по време на свързване, т.е. когато свързвам приложението, което използва моята статична библиотека?


person mch    schedule 06.02.2009    source източник
comment
Въпреки че изглежда има основателни причини за това, дадени в отговорите - съгласен съм с вас. Винаги накрая търся тази настройка на грешното място. Същото нещо и с настройките на Precompiled Headers - има своя собствена категория, вместо да бъде нещо в секцията Preprocessor.   -  person Michael Burr    schedule 07.02.2009


Отговори (6)


Един страничен ефект от дефинициите на препроцесора C като _DLL и _DEBUG, които zdan спомена:

Някои структури от данни (като STL контейнери и итератори) могат да бъдат оразмерени по различен начин по време на изпълнение на отстраняване на грешки, вероятно поради функции като _HAS_ITERATOR_DEBUGGING и _SECURE_SCL. Трябва да компилирате своя код с дефиниции на структура, които са двоично съвместими с библиотеката, която се свързвате с.

Ако смесвате и съпоставяте обектни файлове, които са били компилирани срещу различни библиотеки по време на изпълнение, ще получите предупреждения за свързване като следното:

warning LNK4098: defaultlib 'LIBCMT' conflicts with use of other libs
person bk1e    schedule 07.02.2009

Тези опции могат да добавят дефиниции (__DLL и __DEBUG например), които се използват в заглавните файлове на библиотеката по време на изпълнение. Едно обичайно нещо, което трябва да направите, е да добавите __declspec(dllimport) към декларациите на функциите, когато са свързани динамично.

Компилаторът изглежда също ги използва, за да помогне на линкера да се свърже с правилните библиотеки. Това е обяснено в MSDN.

person zdan    schedule 06.02.2009

Компилаторът трябва да знае дали генерирате еднонишков или многонишков код. По подразбиране компилаторът генерира нишково безопасен код (многонишков). Трябва да му кажете, ако искате единичен код на нишка. Ако промените стойността по подразбиране, компилаторът променя библиотеката по време на изпълнение по подразбиране (винаги можете да отмените това в опциите на командата за свързване, просто се уверете, че избраната от вас библиотека има същия код структура като вашите обектни файлове: еднонишков статичен, многонишков статичен или многонишков DLL). Обърнете внимание, че няма опция за DLL с една нишка (по дефиниция DLL библиотеката за изпълнение ще бъде създадена като безопасна за нишки, тъй като се споделя от множество приложения).

person Tim Ring    schedule 07.02.2009
comment
Също така вече няма статично изпълнение с една нишка (не съм сигурен дали това е започнало във VC2005 или VC2008). - person Michael Burr; 09.02.2009

Ако игнорирате статичното време за изпълнение, тогава получавате същите опции като Linux.

Знам, че статичното време за изпълнение може да бъде полезно, но всъщност никога не съм имало нужда от него. Освен това води до потенциални проблеми при разпределянето/освобождаването на паметта и в резултат намирам за по-лесно просто да използвам DLL runtime.

Наличието на версия Release/Debug е същото като Linux/Unix.
Въпреки че от съображения за ефективност аз също изграждам еднонишкови и многонишкови версии на библиотеки.

person Martin York    schedule 06.02.2009

Вярвам, че причината зад това е, че SEH (структуриран манипулатор на изключения) кодът ще бъде генериран по различен начин в зависимост от коя библиотека за изпълнение свързвате.

person Serafina Brocious    schedule 06.02.2009

Има различен машинен код, генериран за DLL и статични библиотеки.

И на Linux трябва да направите същото, флагът на компилатора се нарича -fPIC, ако искате да изградите споделена библиотека. В противен случай на AMD64 и SPARC (и може би други) ще се срине. На i386 архитектура линкерът е достатъчно умен и не споделя библиотеката в паметта, така че няма да се срине.

person Lothar    schedule 30.09.2010