Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En esta sección se muestran los errores típicos del compilador que se producen al migrar una base de código existente. Estos ejemplos son del código HAL de nivel de sistema, aunque los conceptos se aplican directamente al código de nivel de usuario.
Advertencia C4311 Ejemplo 1
'type cast': truncamiento del puntero de 'void *__ptr64' a 'unsigned long
-
código de
-
pPciAddr->u.AsULONG = (ULONG) CIA_PCI_CONFIG_BASE_QVA;
-
descripción de
-
ptrToUlong es una función o macro insertada, en función del uso. Trunca un puntero a un ULONG. Aunque los punteros de 32 bits no se ven afectados, la mitad superior de un puntero de 64 bits se trunca.
CIA_PCI_CONFIG_BASE_QVA se declara como un PVOID de. La ULONG conversión funciona en el mundo de 32 bits, pero produce un error en el mundo de 64 bits. La solución consiste en obtener un puntero de 64 bits a un ULONG, ya que se cambia la definición de la unión que pPciAddr->u.AsULONG se define en cambios demasiado código.
El uso de la macro ptrToUlong para convertir el PVOID de 64 bits al de ULONG necesario se permite porque tenemos conocimiento sobre el valor específico de CIA_PCI_CONFIG_BASE_QVA. En este caso, este puntero nunca tendrá datos en los 32 bits superiores.
-
solución de
-
pPciAddr->u.AsULONG = PtrToUlong(CIA_PCI_CONFIG_BASE_QVA);
Advertencia C4311 Ejemplo 2
'type cast': truncamiento de puntero de 'struct _ERROR_FRAME *__ptr64' a 'unsigned long
-
código de
-
KeBugCheckEx( DATA_BUS_ERROR,0,0,0,(ULONG)PUncorrectableError );
-
descripción de
-
El problema es que el último parámetro de esta función es un puntero a una estructura de datos. Dado que PUncorrectableError es un puntero, cambia el tamaño con el modelo de programación. Se cambió el prototipo de KeBugCheckEx para que el último parámetro sea un ULONG_PTR. Como resultado, es necesario convertir el puntero de función a un ULONG_PTR.
Puede preguntar por qué PVOID no se usó como último parámetro. En función del contexto de la llamada, el último parámetro puede ser algo distinto de un puntero o quizás un código de error.
-
solución de
-
KeBugCheckEx( DATA_BUS_ERROR,0,0,0,(ULONG_PTR)PUncorrectableError );
Advertencia C4244 Ejemplo 1
'=': conversión de 'struct _CONFIGURATION_COMPONENT *__ptr64' a 'struct _CONFIGURATION_COMPONENT *', posible pérdida de datos
-
código de
-
Component = &CurrentEntry->ComponentEntry;
-
descripción de
-
La función declara la variable Component como un PCONFIGURATION_COMPONENT. Más adelante, la variable se usa en la siguiente asignación que aparece correcta:
Component = &CurrentEntry->ComponentEntry;
Sin embargo, el tipo PCONFIGURATION_COMPONENT se define como:
typedef struct __CONFIGURATION_COMPONENT { ... ... } CONFIGURATION_COMPONENT, * POINTER_32 PCONFIGURATION_COMPONENT;
La definición de tipo para PCONFIGURATION_COMPONENT proporciona un puntero de 32 bits en modelos de 32 y 64 bits porque se declara POINTER_32. El diseñador original de esta estructura sabía que iba a usarse en un contexto de 32 bits en el BIOS y lo definió expresamente para ese uso. Este código funciona bien en Windows de 32 bits porque los punteros tienen un tamaño de 32 bits. En Windows de 64 bits, no funciona porque el código está en contexto de 64 bits.
-
solución de
-
Para solucionar este problema, use CONFIGURATION_COMPONENT * en lugar de la PCONFIGURATION_COMPONENT de 32 bits . Es importante comprender claramente el propósito del código. Si este código está pensado para tocar el BIOS de 32 bits o el espacio del sistema, esta corrección no funcionará.
POINTER_32 se define en Ntdef.h y Winnt.h.
#ifdef (__AXP64__) #define POINTER_32 _ptr32 #else #define POINTER_32 #endif
Advertencia C4242 Ejemplo 2
'=': conversión de '__int64' a 'unsigned long', posible pérdida de datos
-
código de
-
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;
-
descripción de
-
Esta advertencia se genera porque el cálculo usa valores de 64 bits, en este caso punteros y coloca el resultado en un ULONG de 32 bits.
-
solución de
-
Escriba convierta el resultado del cálculo en un ULONG de como se muestra aquí:
ByteSelect1 = (ULONG)(NvDestPtr - (PUCHAR)HalpCMOSRamBase) & CONFIG_RAM_BYTE_MASK;
La difusión de tipos del resultado permite al compilador saber que está seguro del resultado. Dicho esto, asegúrese de que comprende el cálculo y realmente está seguro de que cabe en un ULONG de 32 bits.
Si el resultado no cabe en un ULONG de 32 bits, cambie el tipo base de la variable que contendrá el resultado.
Advertencia C4311: ejemplo 1
'type cast': truncamiento del puntero de 'void *__ptr64' a 'unsigned long'
-
código de
-
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; }
-
descripción de
-
Esta función completa trata con direcciones como enteros, lo que requiere la necesidad de escribir esos enteros de forma portátil. Todas las variables locales, los valores intermedios de los cálculos y los valores devueltos deben ser tipos portátiles.
-
solución de
-
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 es un puntero de 32 bits para Windows de 32 bits y 64 bits para Windows de 64 bits. Apunta a un entero sin signo, ULONG_PTR, que es de 32 bits para Windows de 32 bits y 64 bits para Windows de 64 bits.
Advertencia C4311: ejemplo 2
'type cast': truncamiento del puntero de 'void *__ptr64' a 'unsigned long'
-
código de
-
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);
-
descripción de
-
Aunque todos los valores de QVA (cuasi dirección virtual) son realmente valores de 32 bits en esta fase y caberán en un ULONG, es más coherente tratar todas las direcciones como valores ULONG_PTR siempre que sea posible.
El puntero PciIoSpaceBase contiene la QVA que se crea en la macro HAL_MAKE_QVA. Esta macro devuelve un valor de 64 bits con los 32 bits principales establecidos en cero para que las matemáticas funcionen. Simplemente podríamos dejar el código para truncar el puntero en un ULONG, pero esta práctica no se recomienda mejorar la capacidad de mantenimiento y la portabilidad del código. Por ejemplo, el contenido de una QVA podría cambiar en el futuro para usar algunos de los bits superiores en este nivel, lo que interrumpirá el código.
-
solución de
-
Sea seguro y use ULONG_PTR para todas las matemáticas de dirección y puntero.
HalpCMOSRamBase = (PVOID)((ULONG_PTR)PciIoSpaceBase + CMOS_ISA_PORT_ADDRESS);
Advertencia C4311 Ejemplo 3
'type cast': truncamiento del puntero de 'void *__ptr64' a 'unsigned long'
-
código de
-
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); }
-
descripción de
-
El compilador advierte sobre la dirección de (&) y los operadores de desplazamiento a la izquierda (<<) si se aplican a los tipos de puntero. En el código anterior, Qva es un valor PVOID. Es necesario convertirlo en un tipo entero para realizar las matemáticas. Dado que el código debe ser portátil, use ULONG_PTR en lugar de ULONG.
-
solución de
-
if ( ((ULONG_PTR) Qva & QVA_SELECTORS) == QVA_ENABLE ) { return( (PVOID)( (ULONG_PTR)Qva << IO_BIT_SHIFT ) );
Advertencia C4311 Ejemplo 4
'type cast': truncamiento del puntero de 'void *__ptr64' a 'unsigned long'
-
código de
-
TranslatedAddress->LowPart = (ULONG)HalCreateQva( *TranslatedAddress, va);
-
descripción de
-
TranslatedAddress es una unión que tiene un aspecto similar al siguiente:
typedef union Struct { ULONG LowPart; LONG Highpart; } LONGLONG QuadPart; }
-
solución de
-
Saber cuál podría ser el resto del código en Highpart, podemos seleccionar cualquiera de las soluciones que se muestran aquí.
TranslatedAddress->LowPart = PtrToUlong(HalCreateQva(*TranslatedAddress,va) );
La macro ptrToUlong trunca el puntero devuelto por halCreateQva a 32 bits. Sabemos que la QVA devuelta por HalCreateQva tiene los 32 bits superiores establecidos en cero y la siguiente línea de código establece TranslatedAddress->Highpart en cero.
Con precaución, podríamos usar lo siguiente:
TranslatedAddress->QuadPart = (LONGLONG)HalCreateQva(*TranslatedAddress,va);
Esto funciona en este ejemplo: la macro HalCreateQva devuelve 64 bits, con los 32 bits superiores establecidos en cero. Tenga cuidado de no dejar los 32 bits superiores sin definir en un entorno de 32 bits, lo que esta segunda solución puede hacer realmente.
Advertencia C4311 Ejemplo 5
'type cast': truncamiento del puntero de 'void *__ptr64' a 'unsigned long'
-
código de
-
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;
-
descripción de
-
WindowRegisters:>WindowBase es un puntero y ahora tiene 64 bits. El código indica que desplaza a la derecha este valor de 20 bits. El compilador no nos permitirá usar el operador de desplazamiento a la derecha (>>) en un puntero; por lo tanto, es necesario convertirlo a algún tipo de entero.
-
solución de
-
Wbase.Wbase= PtrToUlong ( (PVOID) ((ULONG_PTR) (WindowRegisters->WindowBase) >> 20));
La conversión a un ULONG_PTR es solo lo que necesitamos. El siguiente problema es Wbase. Wbase es un de ULONG de y es de 32 bits. En este caso, sabemos que el puntero de 64 bits WindowRegisters->WindowBase es válido en los 32 bits inferiores incluso después de cambiarse. Esto hace que el uso de la macro ptrToUlong de sea aceptable, ya que truncará el puntero de 64 bits en un ULONG de 32 bits. La conversión PVOID es necesaria porque ptrToUlong espera un argumento de puntero. Al examinar el código del ensamblador resultante, toda esta conversión de código de C se convierte solo en un quad de carga, desplazarse a la derecha y almacenar largo.