Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
W tym artykule opisano sposób używania środowiska uruchomieniowego języka C.
Oryginalna wersja produktu: Visual C++
Oryginalny numer KB: 94248
Sekcja 1. Dostępne są trzy formy bibliotek czasu wykonywania języka C (CRT)
Istnieją trzy formy biblioteki czasu wykonywania języka C dostarczone z zestawem SDK Win32:
LIBC. BIBLIOTEKA LIB to statycznie połączona biblioteka dla programów jednowątkowych.
LIBCMT. LIB to statycznie połączona biblioteka, która obsługuje programy wielowątkowe.
CRTDLL. LIB to biblioteka importu dla CRTDLL.DLL, która obsługuje również programy wielowątkowe. CRTDLL.DLL sam jest częścią systemu Windows NT.
Wersja 32-bitowa programu Microsoft Visual C++ zawiera również te trzy formularze, jednak CRT w dll nosi nazwę MSVCRT. LIB. Biblioteka DLL jest redystrybucyjny. Jego nazwa zależy od wersji VC++ (czyli MSVCRT10.DLL lub MSVCRT20.DLL). Należy jednak pamiętać, że MSVCRT10.DLL nie jest obsługiwana w systemie Win32s, podczas gdy CRTDLL. Biblioteka LIB jest obsługiwana w systemie Win32s. MSVCRT20.DLL dostępne są dwie wersje: jedna dla systemu Windows NT i druga dla Win32s.
Sekcja 2. Używanie bibliotek CRT podczas kompilowania bibliotek DLL
Podczas kompilowania biblioteki DLL korzystającej z dowolnych bibliotek czasu wykonywania języka C w celu zapewnienia prawidłowego zainicjowania CRT albo
Funkcja inicjowania musi mieć nazwę
DllMain(), a punkt wejścia musi być określony za pomocą opcji konsolidatora-entry:_DllMainCRTStartup@12lub
Punkt wejścia biblioteki DLL musi jawnie wywołać
CRT_INIT()dołączanie procesu i odłączanie procesów.
Dzięki temu biblioteki czasu wykonywania języka C mogą prawidłowo przydzielić i zainicjować dane czasu wykonywania języka C, gdy proces lub wątek jest dołączany do biblioteki DLL, aby prawidłowo wyczyścić dane czasu wykonywania języka C, gdy proces odłącza się od biblioteki DLL, oraz aby globalne obiekty języka C++ w bibliotece DLL były prawidłowo skonstruowane i zdestrukowane.
Przykłady zestawu SDK Win32 używają pierwszej metody. Użyj ich jako przykładu. Zapoznaj się również z dokumentacją DllEntryPoint() programisty Win32 i dokumentacją języka Visual C++ dla programu DllMain(). Należy pamiętać, że DllMainCRTStartup() wywoła metody CRT_INIT() i CRT_INIT() wywoła bibliotekę DllMain(), jeśli istnieje.
Jeśli chcesz użyć drugiej metody i wywołać kod inicjowania CRT samodzielnie, zamiast używać DllMainCRTStartup() metod i DllMain(), istnieją dwie techniki:
Jeśli nie ma funkcji entry, która wykonuje kod inicjowania, określ
CRT_INIT()jako punkt wejścia biblioteki DLL. Zakładając, że uwzględniono NTWIN32. Klucz MAK, który definiujeDLLENTRYwartość @12, dodaj opcję do wiersza linku biblioteki DLL:-entry:_CRT_INIT$(DLLENTRY).lub
Jeśli masz własny punkt wejścia biblioteki DLL, wykonaj następujące czynności w punkcie wejścia:
Użyj tego prototypu dla elementu
CRT_INIT():BOOL WINAPI _CRT_INIT(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved);Aby uzyskać informacje na
CRT_INIT()temat zwracanych wartości, zobacz dokumentację DllEntryPoint. Zwracane są te same wartości.W systemie
DLL_PROCESS_ATTACHiDLL_THREAD_ATTACH(zobacz DllEntryPoint w dokumentacji interfejsu API Win32, aby uzyskać więcej informacji na temat tych flag), wywołaj metodęCRT_INIT(), najpierw, zanim zostaną wywołane jakiekolwiek funkcje czasu wykonywania języka C lub zostaną wykonane jakiekolwiek operacje zmiennoprzecinkowe.Wywołaj własny kod inicjowania procesu/wątku/zakończenia.
Na
DLL_PROCESS_DETACHiDLL_THREAD_DETACHwywołanie ostatniego wywołania, po wywołaniuCRT_INIT()wszystkich funkcji czasu wykonywania języka C i zakończeniu wszystkich operacji zmiennoprzecinkowych.
Pamiętaj, aby przekazać wszystkie CRT_INIT() parametry punktu wejścia; CRT_INIT() oczekuje tych parametrów, więc elementy mogą nie działać niezawodnie, jeśli zostaną pominięte (w szczególności fdwReason jest wymagane, aby określić, czy jest wymagane inicjowanie procesu, czy zakończenie).
Poniżej znajduje się szkielet przykładowa funkcja punktu wejścia, która pokazuje, kiedy i jak wykonać te wywołania CRT_INIT() w punkcie wejścia biblioteki DLL:
BOOL WINAPI DllEntryPoint(HINSTANCE hinstDLL, DWORD fdwReason,
LPVOID lpReserved)
{
if (fdwReason == DLL_PROCESS_ATTACH || fdwReason == DLL_THREAD_ATTACH)
if (!_CRT_INIT(hinstDLL, fdwReason, lpReserved))
return(FALSE);
if (fdwReason == DLL_PROCESS_DETACH || fdwReason == DLL_THREAD_DETACH)
if (!_CRT_INIT(hinstDLL, fdwReason, lpReserved))
return(FALSE);
return(TRUE);
}
Uwaga 16.
Nie jest to konieczne, jeśli używasz programu DllMain() i -entry:_DllMainCRTStartup@12.
Sekcja 3. Używanie NTWIN32. Klucz MAK upraszcza proces kompilacji
W NTWIN32 zdefiniowano makra. Klucz MAK, który może służyć do uproszczenia plików makefile i zapewnienia, że są one prawidłowo skompilowane, aby uniknąć konfliktów. Z tego powodu firma Microsoft zdecydowanie zaleca korzystanie z NTWIN32. Klucz MAK i makra w tym miejscu.
W przypadku kompilacji użyj polecenia: $(cvarsdll) for apps/DLLs using CRT in a DLL.
Aby połączyć, użyj jednego z następujących elementów:
$(conlibsdll) for console apps/DLLs using CRT in a DLL$(guilibsdll) for GUI apps using CRT in a DLL
Sekcja 4. Problemy występujące podczas korzystania z wielu bibliotek CRT
Jeśli aplikacja, która tworzy wywołania w czasie wykonywania języka C, wywołuje łącza do biblioteki DLL, która również wykonuje wywołania czasu wykonywania języka C, należy pamiętać, że jeśli są one połączone z jedną ze statycznie połączonych bibliotek czasu wykonywania języka C (LIBC). LIB lub LIBCMT. LIB), .EXE i DLL będą miały oddzielne kopie wszystkich funkcji czasu wykonywania języka C i zmiennych globalnych. Oznacza to, że dane czasu wykonywania języka C nie mogą być współużytkowane między .EXE a biblioteką DLL. Niektóre problemy, które mogą wystąpić w wyniku:
Przekazywanie buforowanych dojść strumienia z .EXE/DLL do innego modułu
Przydzielanie pamięci za pomocą wywołania w czasie wykonywania języka C w .EXE/DLL i ponowne przydzielanie lub zwalnianie go w innym module
Sprawdzanie lub ustawianie wartości zmiennej global errno w .EXE/DLL i oczekiwanie, że będzie taka sama w innym module. Powiązany problem wywołuje
perror()w przeciwnym module, z którego wystąpił błąd czasu wykonywania języka C, ponieważperror()używa błędu errno.
Aby uniknąć tych problemów, połącz zarówno .EXE, jak i bibliotekę DLL z biblioteką CRTDLL. LIB lub MSVCRT. BIBLIOTEKA LIB, która umożliwia zarówno .EXE, jak i DLL używanie wspólnego zestawu funkcji i danych zawartych w bibliotece CRT w bibliotece DLL, a dane czasu wykonywania języka C, takie jak dojścia strumienia, mogą być następnie współużytkowane przez zarówno .EXE, jak i bibliotekę DLL.
Sekcja 5. Mieszanie typów bibliotek
Bibliotekę DLL można połączyć za pomocą biblioteki CRTDLL. LIB/MSVCRT. BIBLIOTEKA LIB niezależnie od tego, z czym .EXE jest połączona, jeśli unikasz mieszania struktur danych CRT i przekazywania uchwytów plików CRT lub wskaźników CRT FILE* do innych modułów.
Podczas mieszania typów bibliotek są zgodne z następującymi elementami:
Dojścia plików CRT mogą być obsługiwane tylko przez moduł CRT, który je utworzył.
Wskaźniki CRT FILE* mogą być obsługiwane tylko przez moduł CRT, który je utworzył.
Pamięć przydzielona funkcji
malloc()CRT może zostać zwolniona lub przydzielona tylko przez moduł CRT.
Aby to zilustrować, rozważmy następujący przykład:
- .EXE jest połączony z MSVCRT. LIB
- Biblioteka DLL A jest połączona z biblioteką LIBCMT. LIB
- Biblioteka DLL B jest połączona z biblioteką CRTDLL. LIB
Jeśli .EXE tworzy dojście pliku CRT przy użyciu lub _create() _open(), ten uchwyt pliku może być przekazywany tylko do _lseek(), _read()_write(), , _close()itp. w pliku .EXE. Nie przekazuj tego dojścia pliku CRT do żadnej z bibliotek DLL. Nie przekazuj dojścia do pliku CRT uzyskanego z biblioteki DLL do innej biblioteki DLL lub do .EXE.
Jeśli biblioteka DLL A przydziela blok pamięci z biblioteką malloc(), tylko biblioteka DLL A może wywołać free()metodę , _expand()lub realloc() do działania na tym bloku. Nie można wywołać malloc() z biblioteki DLL A i spróbować zwolnić ten blok z .EXE lub biblioteki DLL B.
Uwaga 16.
Jeśli wszystkie trzy moduły zostały połączone z CRTDLL. BIBLIOTEKA LIB lub wszystkie trzy zostały połączone z MSVCRT. LIb, te ograniczenia nie będą stosowane.
Podczas łączenia bibliotek DLL z biblioteką LIBC. BIBLIOTEKA LIB, należy pamiętać, że jeśli istnieje możliwość, że taka biblioteka DLL zostanie wywołana przez program wielowątkowy, biblioteka DLL nie będzie obsługiwać wielu wątków uruchomionych w bibliotece DLL w tym samym czasie, co może powodować poważne problemy. Jeśli istnieje możliwość, że biblioteka DLL zostanie wywołana przez programy wielowątkowe, pamiętaj, aby połączyć ją z jedną z bibliotek obsługujących programy wielowątkowe (LIBCMT). LIB, CRTDLL. LIB lub MSVCRT. LIB).