Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Bu bölümde, mevcut bir kod tabanı geçirildiğinde oluşan tipik derleyici hataları gösterilmektedir. Kavramlar kullanıcı düzeyi kod için doğrudan geçerli olsa da, bu örnekler sistem düzeyindeKI HAL kodundan alınmaktadır.
Uyarı C4311 Örnek 1
'tür ataması' : 'void *__ptr64' değerinden 'unsigned long'a işaretçi kesilmesi
-
Kodu
-
pPciAddr->u.AsULONG = (ULONG) CIA_PCI_CONFIG_BASE_QVA;
-
Açıklaması
-
PtrToUlong, kullanımınıza bağlı olarak satır içi bir işlev veya makrodur. bir ULONGişaretçisini kesilir. 32 bit işaretçiler etkilenmese de, 64 bit işaretçinin üst yarısı kesilir.
CIA_PCI_CONFIG_BASE_QVA PVOIDolarak bildirilir. ULONG ataması 32 bit dünyada çalışır, ancak 64 bit dünyada bir hatayla sonuçlanır. Çözüm, pPciAddr->u.AsULONG birleşiminin tanımının değiştirilmesi çok fazla kodda tanımlandığından, ULONGiçin 64 bit işaretçi almaktır.
64 bit PVOID gerekli ULONG dönüştürmek için PtrToUlong makro kullanılmasına izin verilir çünkü CIA_PCI_CONFIG_BASE_QVA belirli değeri hakkında bilgimiz vardır. Bu durumda, bu işaretçinin üst 32 bitte hiçbir zaman verisi olmaz.
-
Çözümü
-
pPciAddr->u.AsULONG = PtrToUlong(CIA_PCI_CONFIG_BASE_QVA);
Uyarı C4311 Örnek 2
'tür ataması' : 'yapı _ERROR_FRAME *__ptr64' 'unsigned long'a işaretçi kesilmesi
-
Kodu
-
KeBugCheckEx( DATA_BUS_ERROR,0,0,0,(ULONG)PUncorrectableError );
-
Açıklaması
-
Sorun, bu işlevin son parametresinin bir veri yapısının işaretçisi olmasıdır. PUncorrectableError bir işaretçi olduğundan, boyutu programlama modeliyle değiştirir. KeBugCheckEx prototipi, son parametrenin bir ULONG_PTRolması için değiştirildi. Sonuç olarak, işlev işaretçisini bir ULONG_PTRolarak ataması gerekir.
Son parametre olarak neden PVOID kullanılmadığını sorabilirsiniz. Çağrının bağlamlarına bağlı olarak, son parametre işaretçi veya hata kodu dışında bir şey olabilir.
-
Çözümü
-
KeBugCheckEx( DATA_BUS_ERROR,0,0,0,(ULONG_PTR)PUncorrectableError );
Uyarı C4244 Örnek 1
'=' : 'yapı _CONFIGURATION_COMPONENT *__ptr64 ' 'yapısından 'yapı _CONFIGURATION_COMPONENT *' öğesine dönüştürme, olası veri kaybı
-
Kodu
-
Component = &CurrentEntry->ComponentEntry;
-
Açıklaması
-
işlevi, Component değişkenini bir PCONFIGURATION_COMPONENT olarak bildirir. Daha sonra değişkeni, doğru görünen aşağıdaki atamada kullanılır:
Component = &CurrentEntry->ComponentEntry;
Ancak PCONFIGURATION_COMPONENT türü şu şekilde tanımlanır:
typedef struct __CONFIGURATION_COMPONENT { ... ... } CONFIGURATION_COMPONENT, * POINTER_32 PCONFIGURATION_COMPONENT;
PCONFIGURATION_COMPONENT için tür tanımı, POINTER_32bildirildiği için hem 32 bit hem de 64 bit modellerde 32 bit işaretçi sağlar. Bu yapının özgün tasarımcısı, BIOS'ta 32 bitlik bir bağlamda kullanılacağını biliyordu ve bu kullanım için açıkça tanımladı. İşaretçiler 32 bit olduğu için bu kod 32 bit Windows'ta düzgün çalışır. 64 bit Windows'ta kod 64 bit bağlamında olduğundan çalışmaz.
-
Çözümü
-
Bu sorunu geçici olarak çözmek için 32 bit PCONFIGURATION_COMPONENT yerine CONFIGURATION_COMPONENT * kullanın. Kodun amacını net bir şekilde anlamak önemlidir. Bu kod 32 bit BIOS'a veya Sistem alanına dokunmaya yönelikse, bu düzeltme çalışmaz.
POINTER_32 Ntdef.h ve Winnt.h içinde tanımlanır.
#ifdef (__AXP64__) #define POINTER_32 _ptr32 #else #define POINTER_32 #endif
Uyarı C4242 Örnek 2
'=' : '__int64' yerine 'işaretsiz uzun' olarak dönüştürme, olası veri kaybı
-
Kodu
-
ARC_STATUS HalpCopyNVRamBuffer ( IN PCHAR NvDestPtr, IN PCHAR NvSrcPtr, IN ULONG Length ) { ULONG PageSelect1, ByteSelect1; ByteSelect1 = (NvDestPtr - (PUCHAR)HalpCMOSRamBase) & CONFIG_RAM_BYTE_MASK; ByteSelect1 = (NvDestPtr - (PUCHAR)HalpCMOSRamBase) & CONFIG_RAM_BYTE_MASK;
-
Açıklaması
-
Bu uyarı, hesaplama 64 bit değerleri kullandığından ve bu örnekte işaretçiler kullandığından ve sonucu ULONG 32 bityerleştirdiğinden oluşturulur.
-
Çözümü
-
Burada gösterildiği gibi, hesaplamanın sonucunu bir ULONG türe dönüştür:
ByteSelect1 = (ULONG)(NvDestPtr - (PUCHAR)HalpCMOSRamBase) & CONFIG_RAM_BYTE_MASK;
Sonucun tür kaydı, derleyicinin sonuçtan emin olduğunuzu bilmesini sağlar. Bununla birlikte, hesaplamayı anladığınızdan emin olun ve gerçekten ULONG 32 bitsığdığından emin olun.
Sonuç ULONG 32 bitsığmıyorsa, sonucu tutacak değişkenin temel türünü değiştirin.
Uyarı C4311 - Örnek 1
'tür ataması' : 'void *__ptr64' değerinden 'unsigned long' işaretine işaretçi kesilmesi
-
Kodu
-
ULONG HalpMapDebugPort( IN ULONG ComPort, OUT PULONG ReadQva, OUT PULONG WriteQva) { ULONG ComPortAddress; ULONG PortQva; // Compute the port address, based on the desired com port. switch( ComPort ){ case 1: ComPortAddress = COM1_ISA_PORT_ADDRESS; break; case 2: default: ComPortAddress = COM2_ISA_PORT_ADDRESS; } PortQva = (ULONG)HAL_MAKE_QVA(CIA_PCI_SPARSE_IO_PHYSICAL) + ComPortAddress; // Return the QVAs for read and write access. *ReadQva = PortQva; *WriteQva = PortQva; return ComPortAddress; }
-
Açıklaması
-
Bu işlevin tamamı, adresleri tamsayı olarak ele alır ve bu tamsayıları taşınabilir bir şekilde yazma gereksinimini zorunlu kılmaktadır. Tüm yerel değişkenler, hesaplamalardaki ara değerler ve dönüş değerleri taşınabilir türler olmalıdır.
-
Çözümü
-
ULONG_PTR HalpMapDebugPort( IN ULONG ComPort, OUT PULONG_PTR ReadQva, OUT PULONG_PTR WriteQva) { ULONG_PTR ComPortAddress; ULONG_PTR PortQva; // Compute the port address, based on the desired com port. switch( ComPort ){ case 1: ComPortAddress = COM1_ISA_PORT_ADDRESS; break; case 2: default: ComPortAddress = COM2_ISA_PORT_ADDRESS; } PortQva = (ULONG_PTR)HAL_MAKE_QVA(CIA_PCI_SPARSE_IO_PHYSICAL) + ComPortAddress; // Return the QVAs for read and write access. *ReadQva = PortQva; *WriteQva = PortQva; return ComPortAddress; }
PULONG_PTR, 32 bit Windows için 32 bit ve 64 bit Windows için 64 bit olan bir işaretçidir. 32 bit Windows için 32 bit ve 64 bit Windows için 64 bit olan, ULONG_PTRişaretsiz bir tamsayıya işaret eder.
Uyarı C4311 - Örnek 2
'tür ataması' : 'void *__ptr64' değerinden 'unsigned long' işaretine işaretçi kesilmesi
-
Kodu
-
BOOLEAN HalpMapIoSpace ( VOID ) { PVOID PciIoSpaceBase; PciIoSpaceBase = HAL_MAKE_QVA( CIA_PCI_SPARSE_IO_PHYSICAL ); //Map base addresses in QVA space. HalpCMOSRamBase = (PVOID)((ULONG)PciIoSpaceBase + CMOS_ISA_PORT_ADDRESS);
-
Açıklaması
-
Tüm QVA (Quasi Sanal Adresi) değerleri bu aşamada gerçekten 32 bit değerler olsa ve ULONGsığsa da, mümkün olduğunda tüm adresleri ULONG_PTR değerleri olarak işlemek daha tutarlıdır.
İşaretçi PciIoSpaceBase, makro HAL_MAKE_QVA oluşturulan QVA'yi tutar. Bu makro, matematik işleminin çalışması için ilk 32 bitin sıfır olarak ayarlandığı 64 bitlik bir değer döndürür. İşaretçiyi ULONGşeklinde kesecek kodu bırakabiliriz, ancak bu uygulama kod bakımını ve taşınabilirliğini geliştirmek için önerilmez. Örneğin, bir QVA'nın içeriği gelecekte kodu bozarak bu düzeydeki üst bitlerin bazılarını kullanacak şekilde değişebilir.
-
Çözümü
-
Güvenli olun ve tüm adres ve işaretçi matematiği için ULONG_PTR kullanın.
HalpCMOSRamBase = (PVOID)((ULONG_PTR)PciIoSpaceBase + CMOS_ISA_PORT_ADDRESS);
Uyarı C4311 Örnek 3
'tür ataması' : 'void *__ptr64' değerinden 'unsigned long' işaretine işaretçi kesilmesi
-
Kodu
-
PVOID HalDereferenceQva( PVOID Qva, INTERFACE_TYPE InterfaceType, ULONG BusNumber) if ( ((ULONG) Qva & QVA_SELECTORS) == QVA_ENABLE ) { return( (PVOID)( (ULONG)Qva << IO_BIT_SHIFT ) ); } else { return (Qva); }
-
Açıklaması
-
Derleyici, işaretçi türlerine uygulanıyorsa (&) ve sol shift (<<) işleçlerinin adresi hakkında uyarır. Yukarıdaki kodda Qva bir PVOID değeridir. Matematik işlemini gerçekleştirmek için bunu bir tamsayı türüne dönüştürmemiz gerekir. Kodun taşınabilir olması gerektiğinden ULONG yerineULONG_PTR kullanın.
-
Çözümü
-
if ( ((ULONG_PTR) Qva & QVA_SELECTORS) == QVA_ENABLE ) { return( (PVOID)( (ULONG_PTR)Qva << IO_BIT_SHIFT ) );
Uyarı C4311 Örnek 4
'tür ataması' : 'void *__ptr64' değerinden 'unsigned long' işaretine işaretçi kesilmesi
-
Kodu
-
TranslatedAddress->LowPart = (ULONG)HalCreateQva( *TranslatedAddress, va);
-
Açıklaması
-
TranslatedAddress aşağıdakine benzer bir birleşimdir:
typedef union Struct { ULONG LowPart; LONG Highpart; } LONGLONG QuadPart; }
-
Çözümü
-
Kodun geri kalanının Highpart'a yerleştirebileceğini bilerek burada gösterilen çözümlerden birini seçebiliriz.
TranslatedAddress->LowPart = PtrToUlong(HalCreateQva(*TranslatedAddress,va) );
PtrToUlong makro, HalCreateQva tarafından döndürülen işaretçiyi 32 bit olarak kısaltıyor. HalCreateQva tarafından döndürülen QVA'nın üst 32 bit değerinin sıfıra ayarlandığını ve bir sonraki kod satırının TranslatedAddress->Highpart değerini sıfır olarak ayarladığını biliyoruz.
Dikkatli olun, aşağıdakileri kullanabiliriz:
TranslatedAddress->QuadPart = (LONGLONG)HalCreateQva(*TranslatedAddress,va);
Bu, şu örnekte çalışır: HalCreateQva makro 64 bit döndürmektedir ve üst 32 bit sıfır olarak ayarlanmıştır. Üst 32 bitleri 32 bitlik bir ortamda tanımsız bırakmamaya dikkat edin. Bu ikinci çözüm aslında bunu yapabilir.
Uyarı C4311 Örnek 5
'tür ataması' : 'void *__ptr64' değerinden 'unsigned long' işaretine işaretçi kesilmesi
-
Kodu
-
VOID HalpCiaProgramDmaWindow( PWINDOW_CONTROL_REGISTERS WindowRegisters, PVOID MapRegisterBase ) { CIA_WBASE Wbase; Wbase.all = 0; Wbase.Wen = 1; Wbase.SgEn = 1; Wbase.Wbase = (ULONG)(WindowRegisters->WindowBase) >> 20;
-
Açıklaması
-
WindowRegisters->WindowBase bir işaretçidir ve artık 64 bittir. Kod, bu değeri 20 bit sağa kaydırmak için diyor. Derleyici, işaretçi üzerinde right-shift (>>) işlecini kullanmamıza izin vermez; bu nedenle, bunu bir tür tamsayıya dönüştürmemiz gerekir.
-
Çözümü
-
Wbase.Wbase= PtrToUlong ( (PVOID) ((ULONG_PTR) (WindowRegisters->WindowBase) >> 20));
bir ULONG_PTR atama tam da ihtiyacımız olan şey. Sonraki sorun Wbase'dir. Wbase bir ULONG ve 32 bittir. Bu durumda, WindowRegisters->WindowBase 64 bit işaretçisinin kaydırıldıktan sonra bile alt 32 bitte geçerli olduğunu biliyoruz. Bu, 64 bit işaretçiyi ULONG 32 bitkeseceği için PtrToUlong makronun kullanımını kabul edilebilir hale getirir. PtrToUlong işaretçi bağımsız değişkeni beklediğinden PVOID ataması gereklidir. Sonuçta elde edilen assembler koduna baktığınızda, tüm bu C kodu ataması yalnızca bir yük dörtlüsünü oluşturur, sağa kayar ve uzun depolar.