Czy powinienem kompilować z / MD czy / MT?

126

W programie Visual Studio dostępne są flagi kompilacji / MD i / MT, które pozwalają wybrać rodzaj biblioteki środowiska uruchomieniowego C.

Rozumiem różnicę we wdrożeniu, ale nadal nie jestem pewien, którego użyć. Jakie są zalety / wady?

Słyszałem, że jedną z zalet / MD jest to, że pozwala to komuś zaktualizować środowisko wykonawcze (na przykład załatać problem z bezpieczeństwem), a moja aplikacja skorzysta na tej aktualizacji. Chociaż wydaje mi się, że to prawie nie jest funkcja: nie chcę, aby ludzie zmieniali moje środowisko wykonawcze bez pozwolenia mi na testowanie w nowej wersji!

Kilka rzeczy, które mnie interesują:

  • Jak wpłynęłoby to na czas budowy? (prawdopodobnie / MT jest trochę wolniejszy?)
  • Jakie są inne konsekwencje?
  • Którego używa większość ludzi?
andy
źródło
1
Więcej informacji i sugestii można znaleźć na stronie: stackoverflow.com/questions/787216
Weidenrinde

Odpowiedzi:

85

Poprzez dynamiczne łączenie z / MD,

  • jesteś narażony na aktualizacje systemu (na dobre lub na złe),
  • Twój plik wykonywalny może być mniejszy (ponieważ nie ma wbudowanej biblioteki), a
  • Uważam, że przynajmniej segment kodu biblioteki DLL jest współdzielony przez wszystkie procesy, które ją aktywnie używają (co zmniejsza całkowitą ilość zużywanej pamięci RAM).

Odkryłem również, że w praktyce podczas pracy ze statycznie połączonymi bibliotekami binarnymi innych firm, które zostały zbudowane z różnymi opcjami uruchomieniowymi, / MT w głównej aplikacji ma tendencję do powodowania konfliktów znacznie częściej niż / MD (ponieważ wpadną w kłopoty, jeśli środowisko wykonawcze C jest wielokrotnie połączone statycznie, zwłaszcza jeśli są to różne wersje).

Panie Fooz
źródło
10
Bit aktualizacji systemu jest nieco zmniejszony przez SxS. EXE może zadeklarować, której wersji CRT chce (chce, a nie dostaje - aktualizacje zabezpieczeń mogą to unieważnić)
MSalters
1
Czy to oznacza, że ​​jeśli kompiluję przy użyciu MD, a mój program jest zależny od jakiejś biblioteki DLL, program zakończy się niepowodzeniem, jeśli jest uruchomiony na komputerze, na którym biblioteka dll zależności nie istnieje?
gerrytan
5
@gerrytan: Tak, musisz upewnić się, że odpowiednie używane biblioteki DLL są obecne na wszystkich komputerach, na których chcesz uruchomić oprogramowanie. Typowe rozwiązania tego problemu obejmują zainstalowanie przez użytkownika odpowiedniego pakietu redystrybucyjnego MSVC lub użycie instalatora, który wykonuje całą pracę.
Pan Fooz,
@Royi Nie jestem pewien, ale myślę, że /MTbędzie nieco szybszy w czasie wykonywania, ponieważ Twoja aplikacja nie musi za każdym razem wyszukiwać implementacji funkcji wykonawczej, nie jestem ekspertem na tym poziomie, ale jestem prawie pewien Systemy operacyjne będą buforować implementacje środowiska wykonawczego, więc Twoja aplikacja będzie używać wersji buforowanej, więc różnica nie będzie tak duża, UWAGA, wspomniałem, że nie jestem pewien, więc nie traktuj tego komentarza jako argumentu.
Ahmed Kamal
34

Jeśli używasz bibliotek DLL, powinieneś wybrać dynamicznie połączony CRT (/ MD).

Jeśli korzystasz z dynamicznego CRT dla swojego pliku .exe i wszystkich plików .dll, wszystkie będą współużytkować jedną implementację CRT - co oznacza, że ​​wszyscy będą współdzielić jedną stertę CRT, a pamięć przydzielona w jednym pliku .exe / .dll może zostać zwolniona w inne.

Jeśli używasz statycznego CRT dla swojego .exe i wszystkich plików .dll, wszyscy otrzymają oddzielną kopię CRT - co oznacza, że ​​wszyscy będą używać własnej sterty CRT, więc pamięć musi zostać zwolniona w tym samym module, w którym jest został przydzielony. Będziesz także cierpieć z powodu rozdęcia kodu (wiele kopii CRT) i nadmiernego obciążenia środowiska uruchomieniowego (każda sterta przydziela pamięć z systemu operacyjnego, aby śledzić jej stan, a obciążenie może być zauważalne).

JoeG
źródło
20

Uważam, że domyślnym ustawieniem dla projektów utworzonych za pomocą programu Visual Studio jest / MD.

Jeśli używasz / MT, Twój plik wykonywalny nie będzie zależał od biblioteki DLL obecnej w systemie docelowym. Jeśli pakujesz to w instalator, prawdopodobnie nie będzie to problemem i możesz to zrobić.

Sam używam / MT, więc mogę zignorować cały bałagan DLL.

PS Jak podkreśla pan Fooz , należy być konsekwentnym. Jeśli łączysz się z innymi bibliotekami, musisz użyć tej samej opcji, co oni. Jeśli używasz biblioteki DLL innej firmy, prawie pewne jest, że będziesz musiał użyć wersji DLL biblioteki wykonawczej.

Mark Okup
źródło
14

Wolę łączyć się statycznie z / MT.

Nawet jeśli otrzymujesz mniejszy plik wykonywalny z / MD, nadal musisz wysłać kilka bibliotek DLL, aby upewnić się, że użytkownik otrzyma odpowiednią wersję do uruchomienia programu. Ostatecznie twój instalator będzie WIĘKSZY niż podczas łączenia z / MT.

Co gorsza, jeśli zdecydujesz się umieścić swoje biblioteki wykonawcze w katalogu windows, wcześniej czy później użytkownik zainstaluje nową aplikację z różnymi bibliotekami i przy odrobinie szczęścia zepsuje aplikację.

Adrian Grigore
źródło
5
Bardzo zły pomysł, aby "umieścić swoje biblioteki uruchomieniowe w katalogu Windows". Możesz zepsuć inne głupie aplikacje, które zrobiły to samo wcześniej. Użyj SxS i pozwól instalatorowi się nim zająć lub trzymaj się / MT.
MSalters
1
W pełni zgadzam się, że to zły pomysł. Niektórzy jednak to robią, więc opisywałem, dlaczego to nie jest dobry pomysł.
Adrian Grigore
@AdrianGrigore dlaczego nowa aplikacja z różnymi bibliotekami miałaby spowodować przerwę w Twojej aplikacji? Jeśli używasz powiązania / MD, po prostu zaczniesz ładować nowe wersje bibliotek, prawda?
rturrado
4
@rturrado: niezupełnie. Zainstalowanie innych aplikacji na swoich może nadpisać pliki DLL starszymi wersjami. Nowsze wersje zniknęłyby. Jest to powszechnie znane jako „dll hell”, patrz en.wikipedia.org/wiki/DLL_Hell
Adrian Grigore
1
Microsoft zrezygnował z WinSxS w Visual Studio 2010 - biblioteki uruchomieniowe są teraz wdrażane prywatnie lub w system32 ( msdn.microsoft.com/en-us/library/vstudio/dd293574.aspx ).
BCran
8

Problem, na który napotkasz z / MD, polega na tym, że docelowa wersja CRT może nie znajdować się na komputerze użytkownika (zwłaszcza jeśli używasz najnowszej wersji programu Visual Studio, a użytkownik ma starszy system operacyjny).

W takim przypadku musisz dowiedzieć się, jak pobrać odpowiednią wersję na ich komputer.

i_am_jorf
źródło
7

z http://msdn.microsoft.com/en-us/library/2kzt1wy3(VS.71).aspx :

/ MT Definiuje _MT, tak aby wersje procedur wykonawczych specyficzne dla wielowątkowości były wybierane ze standardowych plików nagłówkowych (.h). Ta opcja powoduje również, że kompilator umieszcza nazwę biblioteki LIBCMT.lib w pliku .obj, tak aby konsolidator używał LIBCMT.lib do rozpoznawania symboli zewnętrznych. Do tworzenia programów wielowątkowych wymagany jest / MT lub / MD (lub ich odpowiedniki debugowania / MTd lub / MDd).

/ MD Definiuje _MT i _DLL, dzięki czemu zarówno wersje wielowątkowe, jak i specyficzne dla DLL procedur wykonawczych są wybierane ze standardowych plików .h. Ta opcja powoduje również, że kompilator umieszcza nazwę biblioteki MSVCRT.lib w pliku .obj.

Aplikacje skompilowane z tą opcją są statycznie łączone z MSVCRT.lib. Ta biblioteka udostępnia warstwę kodu, która umożliwia konsolidatorowi rozpoznawanie odwołań zewnętrznych. Rzeczywisty kod roboczy znajduje się w pliku MSVCR71.DLL, który musi być dostępny w czasie wykonywania dla aplikacji połączonych z plikiem MSVCRT.lib.

Kiedy / MD jest używane ze zdefiniowanym _STATIC_CPPLIB (/ D_STATIC_CPPLIB), spowoduje to połączenie aplikacji ze statyczną wielowątkową biblioteką Standard C ++ (libcpmt.lib) zamiast z wersją dynamiczną (msvcprt.lib), jednocześnie dynamicznie łącząc się z głównym CRT za pośrednictwem msvcrt.lib.

Więc jeśli interpretuję to poprawnie, wtedy / MT łączy statycznie, a / MD łączy się dynamicznie.

lothar
źródło
Pytanie brzmiało „którego należy użyć?”, To nie jest odpowiedź.
Leonard Inkret
1

Jeśli budujesz plik wykonywalny, który używa innych bibliotek dll lub bibliotek niż / MD, preferowana jest opcja, ponieważ w ten sposób wszystkie komponenty będą współużytkować tę samą bibliotekę. Oczywiście ta opcja powinna pasować do wszystkich zaangażowanych modułów, tj. Dll / lib / exe.

Jeśli Twój plik wykonywalny nie używa żadnej biblioteki lib lub dll, to jego czyjeś wywołanie. Różnica nie jest teraz zbyt duża, ponieważ aspekt udostępniania nie ma znaczenia.

Więc może możesz uruchomić aplikację za pomocą / MT, ponieważ nie ma ważnego powodu, aby inaczej, ale kiedy nadejdzie czas na dodanie biblioteki lib lub dll, możesz zmienić ją na / MD za pomocą lib / dll, co jest łatwe.

zar
źródło