Aracılığıyla paylaş


C Çalışma Zamanı'nı kullanma

Bu makalede C Çalışma Zamanı'nın nasıl kullanılacağı açıklanmaktadır.

Özgün ürün sürümü: Visual C++
Özgün KB numarası: 94248

Bölüm 1: C Çalışma Zamanı (CRT) Kitaplıklarının Üç Biçimi Kullanılabilir

Win32 SDK ile sağlanan C Çalışma Zamanı kitaplığının üç biçimi vardır:

  • LIBC'ye. LIB, tek iş parçacıklı programlar için statik olarak bağlı bir kitaplıktır.

  • LIBCMT. LIB, çok iş parçacıklı programları destekleyen statik olarak bağlı bir kitaplıktır.

  • CRTDLL. LIB, CRTDLL.DLL için çok iş parçacıklı programları da destekleyen bir içeri aktarma kitaplığıdır. CRTDLL.DLL Kendisi Windows NT'nin bir parçasıdır.

Microsoft Visual C++ 32 bit sürümü de bu üç formu içerir, ancak DLL'deki CRT MSVCRT olarak adlandırılır. LİB. DLL yeniden dağıtılabilir. Adı VC++ sürümüne (MSVCRT10.DLL veya MSVCRT20.DLL) bağlıdır. Ancak MSVCRT10.DLL Win32'lerde desteklenmediğini, CRTDLL'nin ise desteklenmediğini unutmayın. LIB, Win32'lerde desteklenir. MSVCRT20.DLL iki sürümde gelir: biri Windows NT ve diğeri Win32s için.

Bölüm 2: DLL oluştururken CRT kitaplıklarını kullanma

C Çalışma Zamanı kitaplıklarından herhangi birini kullanan bir DLL oluştururken, CRT'nin düzgün şekilde başlatıldığından emin olmak için

  1. Başlatma işlevi adlandırılmalı DllMain() ve giriş noktası bağlayıcı seçeneğiyle belirtilmelidir -entry:_DllMainCRTStartup@12

    veya

  2. DLL'nin giriş noktası, işlem ekleme ve işlem ayırma sırasında açıkça çağrı CRT_INIT() yapmalıdır.

Bu, bir işlem veya iş parçacığı DLL'ye eklenirken C Çalışma Zamanı kitaplıklarının C Çalışma Zamanı verilerini düzgün bir şekilde ayırmasına ve başlatmasına, bir işlem DLL'den ayrılırken C Çalışma zamanı verilerini düzgün bir şekilde temizlemesine ve DLL'deki genel C++ nesnelerinin düzgün bir şekilde oluşturulup yok edilmesine izin verir.

Win32 SDK örneklerinin tümü ilk yöntemi kullanır. Örnek olarak kullanın. Ayrıca için Win32 Programcı Başvurusu'na DllEntryPoint() ve için DllMain()Visual C++ belgelerine bakın. Varsa uygulamanızın DllMainCRTStartup() DllMain() öğesini çağırdığını CRT_INIT() ve CRT_INIT() çağıracağını unutmayın.

İkinci yöntemi kullanmak ve ve DllMain()kullanmak yerine DllMainCRTStartup() CRT başlatma kodunu kendiniz çağırmak istiyorsanız iki teknik vardır:

  1. Başlatma kodu gerçekleştiren bir giriş işlevi yoksa, DLL'nin giriş noktası olarak belirtin CRT_INIT() . NTWIN32 dahil ettiğinizi varsayarsak. @12 olarak tanımlayan DLLENTRY MAK, seçeneğini DLL'nin bağlantı satırına ekleyin:-entry:_CRT_INIT$(DLLENTRY)

    veya

  2. Kendi DLL giriş noktanız varsa, giriş noktasında aşağıdakileri yapın:

    1. için CRT_INIT()bu prototipi kullanın: BOOL WINAPI _CRT_INIT(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved);

      Dönüş değerleri hakkında CRT_INIT() bilgi için DllEntryPoint belgelerine bakın; aynı değerler döndürülür.

    2. ve DLL_THREAD_ATTACH üzerinde DLL_PROCESS_ATTACH (bu bayraklar hakkında daha fazla bilgi için Win32 API başvurusunda DllEntryPoint'e bakın), CRT_INIT()C Çalışma zamanı işlevleri çağrılmadan veya kayan nokta işlemleri gerçekleştirilmeden önce çağrısı yapın.

    3. Kendi işlem/iş parçacığı başlatma/sonlandırma kodunuzu çağırabilirsiniz.

    4. ve DLL_THREAD_DETACHüzerinde DLL_PROCESS_DETACH CRT_INIT(), tüm C Çalışma zamanı işlevleri çağrıldıktan ve tüm kayan nokta işlemleri tamamlandıktan sonra last çağrısında bulunur.

Giriş noktasının tüm parametrelerine CRT_INIT() geçtiğinden emin olun; CRT_INIT() bu parametreleri bekler, bu nedenle atlanırsa işler güvenilir bir şekilde çalışmayabilir (özellikle, işlem başlatma veya sonlandırma gerekip gerekmediğini belirlemek için fdwReason gereklidir).

Aşağıda, DLL giriş noktasında bu çağrıların CRT_INIT() ne zaman ve nasıl yapılacağını gösteren bir iskelet örnek giriş noktası işlevi verilmiştir:

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);
}

Not

ve -entry:_DllMainCRTStartup@12kullanıyorsanız DllMain() bu gerekli değildir.

Bölüm 3: NTWIN32 kullanma. Derleme İşlemini Basitleştirmek için MAK

NTWIN32'de tanımlanan makrolar vardır. MAK, derleme dosyalarınızı basitleştirmek ve çakışmaları önlemek için düzgün bir şekilde oluşturulduklarından emin olmak için kullanılabilir. Bu nedenle Microsoft, NTWIN32 kullanılmasını kesinlikle önerir. MAK ve makrolar.

Derleme için şunu kullanın: $(cvarsdll) for apps/DLLs using CRT in a DLL.

Bağlantı için aşağıdakilerden birini kullanın:

  • $(conlibsdll) for console apps/DLLs using CRT in a DLL
  • $(guilibsdll) for GUI apps using CRT in a DLL

Bölüm 4: Birden çok CRT kitaplığı kullanılırken karşılaşılan sorunlar

C Çalışma Zamanı çağrıları yapan bir uygulama, C Çalışma Zamanı çağrıları da yapan bir DLL'ye bağlantı veriyorsa, her ikisinin de statik olarak bağlı C Çalışma zamanı kitaplıklarından biriyle (LIBC) bağlantılı olduğunu unutmayın. LIB veya LIBCMT. LIB), .EXE ve DLL tüm C Çalışma Zamanı işlevlerinin ve genel değişkenlerin ayrı kopyalarına sahip olur. Bu, C Çalışma zamanı verilerinin .EXE ve DLL arasında paylaşılamayacağı anlamına gelir. Sonuç olarak ortaya çıkabilecek sorunlardan bazıları şunlardır:

  • Arabelleğe alınan akış tanıtıcılarını .EXE/DLL'den diğer modüle geçirme

  • .EXE/DLL'de C Çalışma Zamanı çağrısıyla bellek ayırma ve diğer modülde yeniden ayırma veya boşaltma

  • .EXE/DLL'de genel errno değişkeninin değerini denetleme veya ayarlama ve diğer modülde aynı olmasını bekleme. İlgili bir sorun, errno kullandığından C Çalışma zamanı hatasının oluştuğu perror() karşı modülde çağrı perror() yapıyor.

Bu sorunları önlemek için hem .EXE hem de DLL'yi CRTDLL ile bağlayın. LIB veya MSVCRT. Hem .EXE hem de DLL'nin bir DLL'de CRT içinde yer alan ortak işlev ve veri kümesini kullanmasına olanak tanıyan LIB ve akış tanıtıcıları gibi C Çalışma zamanı verileri hem .EXE hem de DLL tarafından paylaşılabilir.

Bölüm 5: Kitaplık Türlerini Karıştırma

DLL'nizi CRTDLL ile bağlayabilirsiniz. LIB/MSVCRT. CRT veri yapılarını karıştırmaktan ve CRT dosya tanıtıcılarını veya CRT FILE* işaretçilerini diğer modüllere geçirmekten kaçınırsanız, .EXE bağlantınızın ne olduğuna bakılmaksızın LIB.

Kitaplık türlerini karıştırırken aşağıdakilere uyun:

  • CRT dosya tanıtıcıları yalnızca bunları oluşturan CRT modülü tarafından çalıştırılabilir.

  • CRT FILE* işaretçileri yalnızca bunları oluşturan CRT modülü tarafından çalıştırılabilir.

  • CRT işleviyle malloc() ayrılan bellek yalnızca onu ayıran CRT modülü tarafından serbest bırakılabilir veya yeniden yerleştirilebilir.

Bunu göstermek için aşağıdaki örneği göz önünde bulundurun:

  • .EXE MSVCRT ile bağlantılıdır. LİB
  • DLL A, LIBCMT ile bağlantılıdır. LİB
  • DLL B, CRTDLL ile bağlantılıdır. LİB

.EXE veya kullanarak _create() bir CRT dosya tanıtıcısı oluşturursa, bu dosya tanıtıcısı yalnızca .EXE dosyasında , _read(), _write(), _close()vb. öğesine geçirilebilir_lseek()._open() Bu CRT dosya tutamacını iki DLL'ye de geçirmeyin. DLL'den alınan bir CRT dosya tanıtıcısını diğer DLL'ye veya .EXE geçirmeyin.

DLL A ile malloc()bir bellek bloğu ayırırsa, yalnızca DLL A bu blok üzerinde çalışmak için , _expand()veya realloc() çağırabilirfree(). A DLL'sinden çağrı malloc() yapamaz ve bu bloğu .EXE veya B DLL'sinden serbest bırakamazsınız.

Not

Üç modülün de CRTDLL ile bağlantılı olup olmadığını. LIB veya üçü de MSVCRT ile bağlantılıydı. LIb, bu kısıtlamalar geçerli olmaz.

DLL'leri LIBC ile bağlarken. LIB, böyle bir DLL'nin çok iş parçacıklı bir program tarafından çağrılma olasılığı varsa, DLL'nin DLL'de aynı anda çalışan birden çok iş parçacığını desteklemeyeceğini ve bu da büyük sorunlara neden olabileceğini unutmayın. DLL'nin çok iş parçacıklı programlar tarafından çağrılma olasılığı varsa, bunu çok iş parçacıklı programları (LIBCMT) destekleyen kitaplıklardan biriyle bağlayabilirsiniz. LIB, CRTDLL. LIB veya MSVCRT. LIB).