Megosztás:


Gyakori fordítóhibák

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.