Jegyzet
Az oldalhoz való hozzáférés engedélyezést igényel. Próbálhatod be jelentkezni vagy könyvtárat váltani.
Az oldalhoz való hozzáférés engedélyezést igényel. Megpróbálhatod a könyvtár váltását.
Ez a szakasz egy meglévő kódbázis áttelepítése során előforduló tipikus fordítóhibákat mutatja be. Ezek a példák a rendszerszintű HAL-kódból származnak, bár a fogalmak közvetlenül alkalmazhatók a felhasználói szintű kódokra.
Figyelmeztetés C4311 1. példa
'type cast' : pointer csonkolás 'void *__ptr64' 'unsigned long
-
kód
-
pPciAddr->u.AsULONG = (ULONG) CIA_PCI_CONFIG_BASE_QVA; -
leírása
-
PtrToUlong a használattól függően beágyazott függvény vagy makró. Csonkít egy mutatót egy ULONG. Bár a 32 bites mutatókat nem érinti, a 64 bites mutató felső fele csonkolt.
CIA_PCI_CONFIG_BASE_QVA PVOIDdeklarálva van. A ULONG 32 bites világon működik, de a 64 bites világban hibát eredményez. A megoldás az, hogy egy 64 bites mutatót kap egy ULONG, mert a pPciAddr->u.AsULONG által definiált egyesítés definíciójának módosítása túl sok kódban van definiálva.
A PtrToUlong makró használatával konvertálhatja a 64 bites PVOID a szükséges ULONG, mert tudunk a CIA_PCI_CONFIG_BASE_QVA adott értékéről. Ebben az esetben ez a mutató soha nem rendelkezik adatokkal a felső 32 bitben.
-
megoldás
-
pPciAddr->u.AsULONG = PtrToUlong(CIA_PCI_CONFIG_BASE_QVA);
C4311 2. példa figyelmeztetés
'type cast' : pointer csonkolás 'struct _ERROR_FRAME *__ptr64' 'unsigned long
-
kód
-
KeBugCheckEx( DATA_BUS_ERROR,0,0,0,(ULONG)PUncorrectableError ); -
leírása
-
A probléma az, hogy a függvény utolsó paramétere egy adatszerkezetre mutató mutató. Mivel a PUncorrectableError egy mutató, a programozási modell mérete megváltozik. A KeBugCheckEx prototípusát úgy módosították, hogy az utolsó paraméter egy ULONG_PTR. Ennek eredményeképpen a függvénymutatót egy ULONG_PTRkell elhelyezni.
Felmerülhet a kérdés, hogy miért nem PVOID volt az utolsó paraméter. A hívás környezetétől függően előfordulhat, hogy az utolsó paraméter nem mutató vagy hibakód.
-
megoldás
-
KeBugCheckEx( DATA_BUS_ERROR,0,0,0,(ULONG_PTR)PUncorrectableError );
C4244 figyelmeztetés – 1. példa
'=' : átalakítás 'struct _CONFIGURATION_COMPONENT *__ptr64' 'struct _CONFIGURATION_COMPONENT *'-ra, lehetséges adatvesztés
-
kód
-
Component = &CurrentEntry->ComponentEntry; -
leírása
-
A függvény az Összetevő változót PCONFIGURATION_COMPONENT deklarálja. Később a változót a következő, helyesnek tűnő hozzárendelés használja:
Component = &CurrentEntry->ComponentEntry;A PCONFIGURATION_COMPONENT típus azonban a következőképpen van definiálva:
typedef struct __CONFIGURATION_COMPONENT { ... ... } CONFIGURATION_COMPONENT, * POINTER_32 PCONFIGURATION_COMPONENT;A PCONFIGURATION_COMPONENT típusdefiníciója 32 bites mutatót biztosít a 32 bites és a 64 bites modellekben is, mert POINTER_32deklarálva van. A struktúra eredeti tervezője tudta, hogy a BIOS 32 bites környezetében fogja használni, és kifejezetten erre a célra definiálta. Ez a kód jól működik a 32 bites Windowsban, mert a mutatók 32 bitesek. A 64 bites Windowsban ez nem működik, mert a kód 64 bites környezetben van.
-
megoldás
-
A probléma megoldásához a 32 bites PCONFIGURATION_COMPONENT helyett használja a CONFIGURATION_COMPONENT * lehetőséget. Fontos tisztában lenni a kód céljával. Ha ez a kód 32 bites BIOS-t vagy rendszerteret kíván érinteni, ez a javítás nem fog működni.
POINTER_32 az Ntdef.h és a Winnt.h fájlban van definiálva.
#ifdef (__AXP64__) #define POINTER_32 _ptr32 #else #define POINTER_32 #endif
C4242 2. példa figyelmeztetés
'=' : átalakítás '__int64' -ról 'aláíratlan hosszú' értékre, adatvesztés lehetséges
-
kód
-
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; -
leírása
-
Ez a figyelmeztetés azért jön létre, mert a számítás 64 bites értékeket, ebben az esetben mutatókat használ, és az eredményt egy 32 bites ULONGhelyezi el.
-
megoldás
-
Írja be a számítás eredményét egy ULONG- az itt látható módon:
ByteSelect1 = (ULONG)(NvDestPtr - (PUCHAR)HalpCMOSRamBase) & CONFIG_RAM_BYTE_MASK;Az eredmény beírásával a fordító tudhatja, hogy biztos az eredményben. Ennek ellenére győződjön meg róla, hogy megérti a számítást, és valóban biztos benne, hogy illeszkedik egy 32 bites ULONG.
Ha az eredmény nem fér el egy 32 bites ULONG, módosítsa az eredményt tartalmazó változó alaptípusát.
C4311 figyelmeztetés – 1. példa
'type cast' : pointer csonkolás 'void *__ptr64' 'to 'unsigned long'
-
kód
-
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; } -
leírása
-
Ez az egész függvény egész számként kezeli a címeket, ami szükségessé teszi az egész számok hordozható beírását. A helyi változóknak, a számítások köztes értékeinek és a visszaadott értékeknek hordozható típusoknak kell lenniük.
-
megoldás
-
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 egy mutató, amely maga 32 bites a 32 bites Windowshoz és 64 bites a 64 bites Windowshoz. Egy aláíratlan egész számra mutat, ULONG_PTR, amely 32 bites Windows esetén 32, a 64 bites Windows esetében pedig 64 bites.
C4311 figyelmeztetés – 2. példa
'type cast' : pointer csonkolás 'void *__ptr64' 'to 'unsigned long'
-
kód
-
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); -
leírása
-
Annak ellenére, hogy az összes QVA -érték (kvázi virtuális cím) valóban 32 bites érték ebben a szakaszban, és elfér egy ULONG, konzisztensebb, ha lehetséges, az összes címet ULONG_PTR értékként kezelni.
A PciIoSpaceBase mutató a makró HAL_MAKE_QVA létrehozott QVA-t tartalmazza. Ez a makró egy 64 bites értéket ad vissza, amelynek első 32 bitje nullára van állítva, így a matematika működni fog. Egyszerűen hagyhatjuk a kódot, hogy az egérmutatót egy ULONG-csonkíthassuk, de ez a gyakorlat nem ajánlott a kód karbantarthatóságának és hordozhatóságának javítása érdekében. Előfordulhat például, hogy a QVA tartalma a jövőben megváltozik, hogy ezen a szinten használjon néhány felső bitet, feltörve a kódot.
-
megoldás
-
Legyen biztonságos, és használja a ULONG_PTR az összes cím- és mutatómaktikához.
HalpCMOSRamBase = (PVOID)((ULONG_PTR)PciIoSpaceBase + CMOS_ISA_PORT_ADDRESS);
Figyelmeztetés C4311 3. példa
'type cast' : pointer csonkolás 'void *__ptr64' 'to 'unsigned long'
-
kód
-
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); } -
leírása
-
A fordító figyelmezteti a (&) és a bal műszak (<<) operátorok címét, ha a mutatótípusokra alkalmazzák őket. A fenti kódban a Qva egy PVOID érték. Ezt egész számtípusra kell leadnunk a matematikai műveletek elvégzéséhez. Mivel a kódnak hordozhatónak kell lennie, ULONGhelyett használjon ULONG_PTR.
-
megoldás
-
if ( ((ULONG_PTR) Qva & QVA_SELECTORS) == QVA_ENABLE ) { return( (PVOID)( (ULONG_PTR)Qva << IO_BIT_SHIFT ) );
Figyelmeztetés C4311 4. példa
'type cast' : pointer csonkolás 'void *__ptr64' 'to 'unsigned long'
-
kód
-
TranslatedAddress->LowPart = (ULONG)HalCreateQva( *TranslatedAddress, va); -
leírása
-
A TranslatedAddress egy olyan unió, amely a következőhöz hasonlóan néz ki:
typedef union Struct { ULONG LowPart; LONG Highpart; } LONGLONG QuadPart; } -
megoldás
-
Tudva, hogy a kód többi része mit tartalmazhat a Highpartban, az itt látható megoldások közül választhatunk.
TranslatedAddress->LowPart = PtrToUlong(HalCreateQva(*TranslatedAddress,va) );A PtrToUlong makró csonkolja az HalCreateQva által visszaadott mutatót 32 bitesre. Tudjuk, hogy a HalCreateQva által visszaadott QVA a felső 32 bitet nulla értékre állítja, a következő kódkészlet pedig a TranslatedAddress->Highpart to zero értékre.
Óvatosan, a következőket használhatjuk:
TranslatedAddress->QuadPart = (LONGLONG)HalCreateQva(*TranslatedAddress,va);Ez ebben a példában működik: a HalCreateQva makró 64 bitet ad vissza, a felső 32 bit értéke pedig nulla. Csak ügyeljen arra, hogy ne hagyja a felső 32 bitet definiálatlanul egy 32 bites környezetben, amit ez a második megoldás ténylegesen megtehet.
C4311 figyelmeztetés – 5. példa
'type cast' : pointer csonkolás 'void *__ptr64' 'to 'unsigned long'
-
kód
-
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; -
leírása
-
WindowRegisters->WindowBase egy mutató, és most már 64 bit. A kód azt mondja, hogy ezt az értéket 20 bitre kell jobbra tolni. A fordító nem engedi, hogy a mutatón a jobb shift (>>) operátort használjuk; ezért valamilyen egész számra kell vetnünk.
-
megoldás
-
Wbase.Wbase= PtrToUlong ( (PVOID) ((ULONG_PTR) (WindowRegisters->WindowBase) >> 20));A ULONG_PTR az, amire szükségünk van. A következő probléma a Wbase. A Wbase egy ULONG, és 32 bites. Ebben az esetben tudjuk, hogy a 64 bites windowRegisters->WindowBase érvényes az alsó 32 bitben még az eltolódás után is. Ez elfogadhatóvá teszi a PtrToUlong makrót, mivel a 64 bites mutatót 32 bites ULONG. A PVOID leadása azért szükséges, mert PtrToUlong mutatóargumentumot vár. Ha megnézzük az eredményül kapott összeszerelő kódot, ez a C-kód-öntés csak egy terhelési quad lesz, jobbra vált, és hosszú ideig tart.