Transferir Programas De 32 Bits A 64 Bits. 7 Pasos

Última actualización:

El artículo describe los pasos principales que se deben realizar para transferir programas de 32 bits a 64 bits. Se describen los principales problemas que enfrentan los desarrolladores que planean migrar programas de 32 bits a sistemas de 64 bits. Por supuesto, la lista de cuestiones consideradas no está completa, pero esperamos ofrecer una versión más detallada de este artículo en el futuro.

Transferir programas de 32 bits a 64 bits

Estos son los pasos para migrar correctamente aplicaciones de Windows de 32 bits a sistemas Windows de 64 bits:

Paso 1: El modo de 64 bits puede ser diferente. Vamos a solucionarlo

En el marco de una arquitectura de computadora por el término » 64 bits «, se entienden los números enteros de 64 bits y otros tipos de datos de tamaño de este tamaño. Por sistemas de «64 bits» se pueden entender arquitecturas de microprocesador de 64 bits (por ejemplo, EM64T, IA-64) o sistema operativo de 64 bits (por ejemplo, Windows XP Professional x64 Edition).

AMD64 (o x86-64, Intel 64, EM64T, x64) es una arquitectura de microprocesador de 64 bits y un conjunto de instrucciones correspondiente desarrollado por la empresa AMD. Este conjunto de instrucciones fue autorizado por la empresa Intel con el nombre de EM64T (Intel64). La arquitectura AMD64 es una extensión de la arquitectura x86 con total compatibilidad con versiones anteriores.

La arquitectura se generalizó como base para computadoras personales y estaciones de trabajo. IA-64 es una arquitectura de microprocesador de 64 bits desarrollada conjuntamente por las empresas Intel y Hewlett Packard. Se implementa en los microprocesadores Itanium e Itanium 2. La arquitectura se utiliza principalmente en servidores multiprocesador y sistemas de clúster.

Quizás te puede interesar: Cómo descargar dispositivo PCI para Windows 7 64 bits

AMD64 e IA-64 son dos arquitecturas diferentes de 64 bits, que son incompatibles entre sí. Esta es la razón por la que los desarrolladores deben decidir a la vez si necesitan admitir ambas arquitecturas o solo una. En la mayoría de los casos, si no desarrolla software altamente personalizado para sistemas de clúster, o no implementa su propio DBMS de alto rendimiento, lo más probable es que tenga que implementar soporte solo para la arquitectura AMD64, que es mucho más popular que IA. -64.

Se trata especialmente de software para el mercado de PC, que está ocupado casi al 100% por la arquitectura AMD64. Más adelante en el artículo hablaremos solo sobre la arquitectura AMD64 (EM64T, x64), ya que hoy en día es la más actual para los desarrolladores de software de aplicaciones. Hablando de diferentes arquitecturas, debemos mencionar la noción «Modelo de datos».

Por modelo de datos entendemos las correlaciones entre los tamaños de letra aceptados en el marco del entorno de desarrollo. Puede haber varias herramientas de desarrollo que se adhieran a diferentes tipos de datos para un sistema operativo. Pero, por lo general, solo domina un modelo que corresponde más al entorno de hardware y software.

Un ejemplo de ello es Windows de 64 bits, cuyo modelo de datos original es LLP64. Pero por motivos de compatibilidad, Windows de 64 bits admite la ejecución de programas de 32 bits que operan en el modo de modelo de datos ILP32LL. La Tabla 1 brinda información sobre los modelos de datos básicos.

Transferir programas de 32 bits a 64 bits

El modelo de datos que se utiliza influye mucho en el proceso de desarrollo de las aplicaciones de 64 bits, ya que es preciso que se tenga en cuenta el tamaño de los datos que se utilizan en el código de los programas.

Paso 2: Descubre si necesitas la versión de 64 bits de tu producto

Deberías empezar a dominar los sistemas de 64 bits con la pregunta: «¿Realmente necesito reconstruir mi proyecto para un sistema de 64 bits?» le das una respuesta a esta pregunta sólo después de haberla pensado detenidamente. Por un lado, puedes quedarte atrás de tus rivales si no ofreces soluciones de 64 bits. Por otro lado, es posible que pierdas el tiempo desarrollando una aplicación de 64 bits que no proporcionará ninguna ventaja competitiva. Hagamos una lista de los factores básicos que te ayudarán a tomar una decisión.

2.1. Duración del ciclo de vida de las aplicaciones

No debes crear la versión de 64 bits de una aplicación con un ciclo de vida corto. Gracias al subsistema WOW64, las aplicaciones antiguas de 32 bits funcionan bastante bien en sistemas Windows de 64 bits, y es por eso que no tiene sentido hacer un programa de 64 bits, ya que no será compatible en 2 años.

Además, la práctica muestra que la migración a versiones de Windows de 64 bits se ha retrasado, y quizás la mayoría de sus usuarios utilizarán solo la versión de 32 bits de la solución de programa a corto plazo.

Si planeas el desarrollo y soporte a largo plazo de un producto de programa, debes comenzar a trabajar con la versión de 64 bits de tu solución. Puedes hacer esto sin prisa, pero ten en cuenta que cuanto más tiempo no tengas una versión completa de 64 bits, más dificultades enfrentarás para admitir esta aplicación instalada en versiones de Windows de 64 bits.

2.2. El uso intensivo de recursos de una aplicación

La recompilación de un programa para un sistema de 64 bits le permitirá utilizar grandes tamaños de memoria principal y también acelerará su funcionamiento en un 5-15%. Se obtendrá un aumento del 5-10% debido al uso de las capacidades arquitectónicas del procesador de 64 bits, por ejemplo, un mayor número de registros. El resto del aumento de velocidad del 1 al 5% se explica por la ausencia de la capa WOW64, que traduce las llamadas API entre aplicaciones de 32 bits y un sistema operativo de 64 bits.

Si tu programa no funciona con datos de gran tamaño (más de 2 GB) y la velocidad de su funcionamiento no es crucial, la migración a un sistema de 64 bits no será tan urgente en un futuro próximo. Por cierto, incluso las aplicaciones simples de 32 bits pueden obtener ventajas al iniciarse en un entorno de 64 bits.

Quizás sepas que un programa creado con la tecla / LARGEADDRESSAWARE: YES puede asignar hasta 3 GB de memoria, si Windows de 32 bits se inicia con la tecla. Este programa de 32 bits lanzado en un sistema de 64 bits puede asignar casi 4 GB de memoria (en la práctica, alrededor de 3,5 GB).

2.3. Desarrollo de bibliotecas

Si desarrollas bibliotecas, componentes u otros elementos con la ayuda de desarrolladores externos que crean su propio software, debes actuar rápidamente mientras creas la versión de 64 bits de tu producto. De lo contrario, los clientes interesados en el lanzamiento de versiones de 64 bits, tendrán que buscar soluciones alternativas.

Por ejemplo, algunos desarrolladores de seguridad de software y hardware respondieron lentamente lanzando programas de 64 bits, y eso hizo que algunos clientes buscaran otras herramientas para proteger sus programas.

Una ventaja adicional de lanzar la versión de 64 bits de una biblioteca es que puedes venderla como un producto separado. Por lo tanto, tus clientes que deseen crear aplicaciones tanto de 32 bits como de 64 bits deberán comprar 2 licencias diferentes.

2.4. Dependencia de su producto en bibliotecas de terceros

Antes de planificar el trabajo en la creación de la versión de 64 bits de tu producto, averigüa si se utilizan versiones de 64 bits de las bibliotecas y los componentes. Además de esto, conoce la política de precios de la versión de 64 bits de una biblioteca. Si no se proporciona soporte, busca soluciones alternativas que admitan sistemas de 64 bits de antemano.

2.5. Uso de aplicaciones de 16 bits

Si tus soluciones aún utilizan unidades de 16 bits, ya es hora de que te deshagas de ellas. Las aplicaciones de 16 bits en las versiones de Windows de 64 bits no son compatibles. Deberíamos explicar una cosa aquí sobre el uso de instaladores de 16 bits. Todavía se utilizan para instalar algunas aplicaciones de 32 bits.

Existe un mecanismo especial que reemplaza algunos de los instaladores de 16 bits más populares por sus versiones más recientes. Puede llevar a la falsa idea de que los programas de 16 bits todavía funcionan en el entorno de 64 bits. Recuerda: no es así.

2.6. Ensamblaje de códigos

No olvides que el uso de un código ensamblador de gran tamaño puede aumentar significativamente el costo de crear la versión de 64 bits de una aplicación. Después de pensar en todos los factores enumerados y sopesar todos los pros y los contras, decide si necesits trasladar tu proyecto a sistemas de 64 bits. Si la respuesta es sí, podemos ir más lejos.

Paso 3: Kit de herramientas

Si has decidido desarrollar la versión de 64 bits de tu producto y estás dispuesto a dedicarle tiempo, todavía no es suficiente para garantizar el éxito. El punto es que debes poseer todo el conjunto de herramientas necesario, y aquí puedes enfrentar algunas dificultades. La ausencia de un compilador de 64 bits puede ser el problema más simple pero el más insuperable.

Si todo está claro acerca de la ausencia de un compilador de 64 bits, otros problemas similares pueden parecer menos transparentes y ocurrir solo en la etapa de portar el proyecto a una nueva arquitectura. Es por eso que nos gustaría aconsejarte que averigües de antemano si existen todos los componentes necesarios que necesitarás para implementar la versión de 64 bits de tu producto. Puedes enfrentarte a sorpresas desagradables.

Por supuesto, es imposible enumerar aquí todo lo que puedes necesitar para un proyecto, pero continuaremos la lista que te ayudará a orientarte, y tal vez a recordar otras cosas necesarias para implementar tu proyecto de 64 bits:

3.1. Un compilador de 64 bits

Apenas hay más que decir sobre la importancia de tener un compilador de 64 bits. Simplemente debe ser así. Si planeas desarrollar aplicaciones de 64 bits utilizando la última versión de Visual Studio, la siguiente Tabla 2 te ayudará a comprender cuál de las ediciones de Visual Studio necesitas.

Compilador de 64 bits

3.2. Computadoras de 64 bits bajo control de un sistema operativo de 64 bits

Por supuesto, puedes usar máquinas virtuales para iniciar aplicaciones de 64 bits en computadoras de 32 bits, pero es demasiado inconveniente y no proporcionará el nivel de pruebas necesario. Es deseable que las máquinas tengan no menos de 4-8 GB de memoria principal.

3.3. Versiones de 64 bits de todas las bibliotecas utilizadas

Si las bibliotecas se presentan en códigos fuente, debe haber una configuración de 64 bits del proyecto. Puede ser una tarea difícil e ingrata actualizar la biblioteca para un sistema de 64 bits por tu cuenta, y el resultado puede ser poco confiable y contener errores. Además, puede violar los acuerdos de licencia con estas acciones. Si usas bibliotecas en forma de unidades binarias, también debes averiguar si hay unidades de 64 bits.

No puedes utilizar una DLL de 32 bits dentro de una aplicación de 64 bits. Puedes crear un vínculo especial a través de COM, pero será una tarea grande y difícil separada. También ten en cuenta que es posible que debas gastar algo de dinero extra para comprar la versión de 64 bits de la biblioteca.

3.4. Ausencia de código ensamblador integrado

Visual C ++ no admite un ensamblador en línea de 64 bits. Debes utilizar un ensamblador externo de 64 bits (por ejemplo, MASM) o poseer una implementación con la misma funcionalidad en C / C ++.

3.5. Actualización de la metodología de prueba

Significa una reconstrucción considerable de la metodología de prueba, la actualización de las pruebas unitarias y el uso de nuevas herramientas. Hablaremos de ello con más detalle más adelante, pero no olvides tenerlo en cuenta en la etapa de evaluación de los costos de tiempo en la migración de una aplicación a un nuevo sistema.

3.6. Nuevos datos para probar

Si estás desarrollando aplicaciones de uso intensivo de recursos utilizando una gran cantidad de memoria principal, debes proporcionar el reabastecimiento de la base de datos de entrada de prueba. Durante las pruebas de carga de las aplicaciones de 64 bits, es conveniente exceder los límites de 4 GB de la memoria utilizada. Muchos errores pueden ocurrir solo en estas condiciones.

3.7. Sistemas de seguridad de 64 bits

El sistema de seguridad que se utilices debe proporcionar compatibilidad total con sistemas de 64 bits. Durante mucho tiempo no ha existido un sistema de protección automática de archivos binarios de 64 bits (programa Hasp Envelop).

Por lo tanto, el mecanismo de seguridad tenía que implementarse manualmente dentro del código del programa, y ​​esa era una tarea más difícil que exigía profesionalidad y tiempo. No te olvides de cuestiones relacionadas con la seguridad, las actualizaciones del sistema, entre otros.

3.8. Instalador

Necesitas un nuevo instalador capaz de instalar completamente aplicaciones de 64 bits. Nos gustaría advertirte sobre un error muy típico. Es la creación de instaladores de 64 bits para instalar productos de programas de 32/64 bits. Al preparar la versión de 64 bits de una aplicación, los desarrolladores a menudo quieren hacer que el «modo de 64 bits» sea absoluto y crear un instalador de 64 bits olvidando que aquellos que usan un sistema operativo de 32 bits simplemente no puedan iniciar tal paquete de instalación.

Presta atención a que no es la aplicación de 32 bits incluida en el kit de distribución junto con la de 64 bits, sino el propio instalador. Porque si el kit de distribución es una aplicación de 64 bits, por supuesto que no funcionará en un sistema operativo de 32 bits. Lo más desagradable es que un usuario no podrá adivinar por qué está sucediendo.

Paso 4: Configuración de un proyecto en Visual Studio 2005/2008

La creación de la configuración de 64 bits de un proyecto en Visual Studio parece bastante simple. Las dificultades comenzarán en la etapa de construcción de una nueva configuración y la búsqueda de errores en ella. Para crear la configuración de 64 bits en sí, debes realizar los siguientes 4 pasos:

Paso 1: inicia el administrador de configuración, como se muestra en la imagen 1:

Transferir programas de 32 bits a 64 bits

Paso 2: en el administrador de configuración, elige el soporte de la nueva plataforma:

Transferir programas de 32 bits a 64 bits

Paso 3: elige la plataforma de 64 bits (x64) y, como base, la configuración de la versión de 32 bits. Visual Studio corregirá automáticamente las configuraciones que influyen en el modo de construcción.

Transferir programas de 32 bits a 64 bits

Paso 4: se completó la adición de una nueva configuración y ahora puedes elegir la versión de configuración de 64 bits y comenzar a compilar una aplicación de 64 bits. La elección de la configuración de 64 bits para la construcción se muestra en la imagen4 4.

Transferir programas de 32 bits a 64 bits

Si tienes suerte, no necesitarás configurar adicionalmente un proyecto de 64 bits. Pero depende en gran medida del proyecto, su complejidad y la cantidad de bibliotecas utilizadas. Lo único que debes cambiar a la vez es el tamaño de la pila. Si el tamaño de la pila en tu proyecto está establecido de forma predeterminada, que es 1 MB, debes definirlo como 2 MB para la versión de 64 bits.

No es necesario, pero es mejor asegurarse de antemano. Si usas un tamaño diferente al predeterminado, tiene sentido aumentarlo dos veces para la versión de 64 bits. Para hacer esto, busca y cambia los parámetros Stack Reserve Size y Stack Commit Size en la configuración del proyecto.

Paso 5: Compilación de una aplicación

Aquí deberíamos informarte sobre los problemas típicos que ocurren en la etapa de compilación de la configuración de 64 bits, discutir qué problemas ocurren en las bibliotecas de terceros, decirte que en el código relacionado con las funciones de WinAPI, el compilador no permitirá colocar un puntero en tipo LONG, y tendrás que actualizar tu código y usar el tipo LONG_PTG. Y hay mucho más que decir.

Desafortunadamente, hay tantos problemas y los errores varían tanto que no podemos describirlos todos en un artículo, ni siquiera en un libro. Tendrás que revisar todos los errores que te muestra el compilador y todas las advertencias nuevas que no estaban allí antes y, en cada caso particular, averiguar cómo actualizar el código.

Describamos aquí solo los tipos que pueden ser de interés para los desarrolladores al portar aplicaciones. La mayoría de los errores de recompilación se relacionarán con el uso de estos mismos tipos:

  • En t 32 / 32: tipo básico. En sistemas de 64 bits sigue siendo de 32 bits.
  • Long 32 / 32: tipo básico. En los sistemas Windows de 64 bits sigue siendo de 32 bits. Ten en cuenta que en los sistemas Linux de 64 bits, este tipo se extendió a 64 bits. No lo olvides si desarrollas código que debería compilarse para sistemas Windows y Linux.
  • size_t 32 / 64: tipo básico sin firmar. El tamaño del tipo se elige de tal manera que pueda escribir en él el tamaño máximo de una matriz teóricamente posible. Puedes poner de forma segura un puntero en el tipo size_t (excepto para punteros a funciones de clase, pero este es un caso especial).
  • ptrdiff_t 32 / 64: similar al tipo size_t, pero este es un tipo firmado. El resultado de la expresión donde se resta un puntero del otro (ptr1-ptr2) tendrá el tipo ptrdiff_t.
  • Puntero 32 / 64: el tamaño del puntero depende directamente del tamaño de la plataforma. Ten cuidado al convertir punteros a otros tipos.
  • __int64 64 / 64: tipo firmado de 64 bits.
  • DWORD 32 / 32: tipo sin firmar de 32 bits. En WinDef.h se define como: typedef unsigned long DWORD;
  • DWORDLONG 64/64: tipo sin firmar de 64 bits. En WinNT.h se define como: typedef ULONGLONG DWORDLONG.
  • DWORD_PTR 32/64: tipo sin signo en el que se puede colocar un puntero. En BaseTsd.h se define como: typedef ULONG_PTR DWORD_PTR.
  • DWORD32 32 / 32: tipo sin firmar de 32 bits. En BaseTsd.h se define como: typedef unsigned int DWORD32.
  • DWORD64 64 / 64: tipo sin firmar de 64 bits. En BaseTsd.h se define como: typedef unsigned __int64 DWORD64.
  • HALF_PTR 16 / 32: la mitad de un puntero. En Basetsd.h se define como: #ifdef _WIN64. typedef int HALF_PTR; #else typedef short HALF_PTR; #endif
  • INT_PTR 32 / 64: tipo firmado en el que se puede colocar un puntero. En BaseTsd.h se define como: #if definido (_WIN64) typedef __int64 INT_PTR; #else typedef int INT_PTR; #endif
  • Long 32 / 32: tipo firmado que permaneció en 32 bits. Por eso, en muchos casos, ahora se debería utilizar LONG_PTR. En WinNT.h se define como: typedef long LONG;
  • LONG_PTR 32 / 64: tipo firmado en el que se puede colocar un puntero. En BaseTsd.h se define como: #if definido (_WIN64) typedef __int64 LONG_PTR; #else typedef long LONG_PTR; #endif.
  • LPARAM 32 / 64: parámetro para enviar mensajes. En WinNT.h se define como: typedef LONG_PTR LPARAM.
  • TAMAÑO_T 32 / 64: análogo de tipo size_t. En BaseTsd.h se define como: typedef ULONG_PTR SIZE_T.
  • SSIZE_T 32/64: Análogo de tipo ptrdiff_t. En BaseTsd.h se define como: typedef LONG_PTR SSIZE_T.
  • ULONG_PTR 32 / 64: tipo sin signo en el que se puede colocar un puntero. En BaseTsd.h se define como: #if definido (_WIN64) typedef unsigned __int64 ULONG_PTR; #else typedef unsigned long ULONG_PTR; #endif.
  • WORD 16 / 16: Tipo de 16 bits sin firmar. En WinDef.h se define como: typedef unsigned short WORD.
  • WPARAM 32 / 64: parámetro para enviar mensajes. En WinDef.h se define como: typedef UINT_PTR WPARAM.

Estos son los tipos que se deben tener en cuenta al migrar programas de 32 bits en sistemas Windows de 64 bits.

Tal vez quieras saber: Cómo Utilizar Toda La Memoria RAM En Windows 10

6. Diagnóstico de errores ocultos

Si crees que después de corregir todos los errores de compilación obtendrás una aplicación de 64 bits tan esperada, tenemos que decepcionarte. La parte más difícil aún está por venir. En la etapa de compilación, corregirá los errores más explícitos que el compilador haya logrado detectar, y que en su mayoría se relacionan con la imposibilidad de conversión implícita de tipos.

Pero esto es solo una pequeña parte del problema. La mayoría de los errores están ocultos. Desde el punto de vista del lenguaje abstracto C++, estos errores parecen seguros y están disfrazados por conversiones de tipo explícitas. El número de tales errores es mucho mayor que el número de errores detectados en la etapa de compilación.

No debes poner tus esperanzas en la clave / Wp64. Esta clave se presenta a menudo como un medio maravilloso para buscar errores de 64 bits. En realidad, la tecla / Wp64 simplemente te permite recibir algunos mensajes de advertencia sobre la incorrección de algunas secciones de código en el modo de 64 bits, mientras se compila el código de 32 bits.

Al compilar código de 64 bits, estas advertencias se mostrarán de todos modos. Y es por eso que la clave / Wp64 se ignora al compilar una aplicación de 64 bits. Y seguramente esta clave no ayudará en la búsqueda de errores ocultos. Consideremos varios ejemplos de errores ocultos.

6.1. Conversión de tipo explícita

La clase de error más simple (pero ciertamente no la más fácil de detectar) se relaciona con las conversiones de tipos explícitas, cuando se cortan bits significativos. Un ejemplo popular es la conversión de punteros a tipos de 32 bits al transferirlos a funciones como SendMessage:

Compilación de una aplicación

Aquí, la conversión de tipo explícita se utiliza para convertir un puntero en un tipo numérico. Para una arquitectura de 32 bits, este ejemplo es correcto ya que el último parámetro de la función SendMessage tiene el tipo LPARAM, que coincide con DWORD en una arquitectura de 32 bits. Para una arquitectura de 64 bits, DWORD es incorrecto y debe reemplazarse con LPARAM. El tipo LPARAM tiene tamaños de 32 o 64 bits, según la arquitectura.

Este es un caso simple, pero la conversión de tipos a menudo parece más complicada y es imposible detectarla usando las advertencias del compilador o buscando en el texto del programa. Las conversiones de tipo explícitas suprimen el diagnóstico del compilador, ya que están destinadas a este mismo propósito: decirle al compilador que la conversión de tipo es correcta y que el programador es responsable de la seguridad del código.

La búsqueda explícita tampoco ayudará. Los tipos pueden tener nombres no estándar (definidos por el programador a través de typedef) y el número de métodos para realizar la conversión de tipos explícita también es grande. Para diagnosticar estos errores de forma segura, debes utilizar un conjunto de herramientas especial, como los analizadores Viva64 o PC-Lint.

6.2. Conversión de tipo implícita

El siguiente ejemplo se relaciona con la conversión de tipo implícita, cuando también se pierden bits importantes. El código de la función fread realiza la lectura del archivo, pero es incorrecto cuando se intenta leer más de 2 GB en un sistema de 64 bits.

Conversión de tipo implícita

La función __fread devuelve el tipo size_t, pero el tipo int se usa para almacenar el número de bytes leídos. Como resultado, en tamaños grandes de datos leídos, la función puede devolver un número falso de bytes. Se puede decir que es un código analfabeto para principiantes, que el compilador anunciará este tipo de conversión y que este código es realmente fácil de encontrar y corregir. Esto es en teoría.

En la práctica, todo puede ser bastante diferente en el caso de grandes proyectos. Este ejemplo está tomado del código fuente de FreeBSD. ¡El error se corrigió en diciembre de 2008! Ten en cuenta que la primera versión (experimental) de 64 bits de FreeBSD se lanzó en junio de 2003.

6.3. Bits y cambios

Es fácil cometer un error en el código mientras se trabaja con bits separados. El siguiente tipo de error se relaciona con las operaciones de turno. Aquí hay un ejemplo:

Bits y cambios

Este código funciona bien en una arquitectura de 32 bits y te permite establecer bits con números del 0 al 31 a la unidad. Después de trasladar el programa a una plataforma de 64 bits, deberás establecer los bits 0 a 63. Pero este código nunca establecerá los bits 32-63.

Presta atención a que «1» tiene tipo int, y cuando ocurre un cambio en 32 posiciones, se producirá un desbordamiento como se muestra en la imagen. Ya sea que obtengamos 0 (Figura B) o 1 (Figura C), como resultado, depende de la implementación del compilador.

Bits y cambios

Para corregir el código, necesitamos hacer «1» constante del mismo tipo que la variable de máscara:

ptrdiff_t mask = ptrdiff_t(1) << bitNum;

También presta atención al hecho de que el código incorrecto conduce a un error más. Al configurar 31 bits en un sistema de 64 bits, el resultado de la función será el valor 0xffffffff80000000. El resultado de 1 << 31 expresión es el número negativo -2147483648. En una variable entera de 64 bits, este número se presenta como 0xffffffff80000000.

Bits y cambios

6.4. Números mágicos

Las constantes mágicas, es decir, los números con la ayuda de los cuales se define el tamaño de este o aquel tipo, pueden causar muchos problemas. La decisión correcta sería usar operadores sizeof () para estos propósitos, pero en un programa grande, una sección de código antiguo aún puede estar oculta donde, como creen los programadores, el tamaño del puntero es de 4 bytes y en size_t siempre es de 32 bits. Por lo general, estos errores tienen el siguiente aspecto:

Números mágicos

A continuación se muestra los números básicos con los que debes tener cuidado al transferir programas de 32 bits a 64 bits.

Números mágicos

Estos con los valores mágicos básicos que son peligrosos al migrar aplicaciones desde una plataforma de 32 bits a 64 bits.

6.5. Errores relacionados con el uso de variables de 32 bits como índices

En los programas que procesan datos de gran tamaño, pueden producirse errores relacionados con la indexación de matrices grandes o bucles eternos. El siguiente ejemplo contiene 2 errores:

Errores relacionados con el uso de variables de 32 bits como índices

El primer error aquí es que si el tamaño de los datos que se procesan excede los 4 GB (0xFFFFFFFF), puede ocurrir un bucle eterno ya que la variable ‘i’ tiene el tipo ‘unsigned‘ y nunca alcanzará el valor 0xFFFFFFFF. Escribimos deliberadamente que puede ocurrir pero no necesariamente. Depende del código que construirá el compilador.

Por ejemplo, en el modo de depuración estará presente el bucle eterno, y en el código de liberación no habrá bucle ya que el compilador decidirá optimizar el código usando un registro de 64 bits para el contador, y el bucle será correcto. Todo esto agrega mucha confusión, y el código que funcionó ayer puede fallar hoy.

El segundo error se relaciona con analizar la matriz de principio a fin para determinar qué valores de índices negativos se utilizan. Este código funcionará bien en el modo de 32 bits, pero cuando se ejecuta en una computadora de 64 bits, el acceso fuera de los límites de la matriz se producirá en la primera iteración del bucle y el programa se bloqueará. Estudiemos la razón de tal comportamiento. De acuerdo con las reglas de C++, la expresión «-i – uno» en un sistema de 32 bits se calculará de la siguiente manera: (en el primer paso i = 0):

La expresión «-i» tiene un tipo sin signo y un valor 0x00000000u.

La variable ‘one‘ se extenderá del tipo ‘int‘ al tipo sin signo y será igual a 0x00000001u. Nota: el tipo int se extiende (según el estándar C ++) hasta el tipo ‘unsigned‘ si participa en una operación donde el segundo argumento tiene un tipo unsigned. Se lleva a cabo una operación de resta en la que participan dos valores de tipo unsigned, y el resultado de la operación es 0x00000000u – 0x00000001u = 0xFFFFFFFFu. Ten en cuenta que el resultado tendrá un tipo sin firmar.

En un sistema de 32 bits, el acceso a la matriz por el índice 0xFFFFFFFFu es lo mismo que usar el índice -1. Eso es end [0xFFFFFFFFu], es un análogo de end [-1]. Como resultado, los elementos de la matriz se procesarán correctamente. En un sistema de 64 bits, la situación será bastante diferente con respecto al último punto.

El tipo sin firmar se extenderá al tipo ptfdiff_t firmado, y el índice de la matriz será igual a 0x00000000FFFFFFFFi64. Como resultado, se producirá un desbordamiento. Para corregir el código, debes usar los tipos ptrdiff_t y size_t.

6.6. Errores relacionados con el cambio de los tipos de funciones utilizadas

Hay errores que no son culpa de nadie, pero siguen siendo errores. Imagínate que hace mucho, mucho tiempo en una galaxia lejana (en Visual Studio 6.0), se desarrolló un proyecto que contenía la clase CSampleApp, un sucesor de CWinApp. En la clase básica hay una función virtual WinHelp. El sucesor superpone esta función y realiza todas las acciones necesarias. Este proceso se muestra en la siguiente figura.

Errores relacionados con el cambio de los tipos de funciones utilizadas

Posteriormente el proyecto se traslada a Visual Studio 2005, donde el prototipo de la función WinHelp ha cambiado, pero nadie se dio cuenta porque en el modo de 32 bits los tipos DWORD y DWORD_PTR coincidían y el programa seguía funcionando correctamente.

Errores relacionados con el cambio de los tipos de funciones utilizadas

El error está esperando a revelarse en un sistema de 64 bits, donde los tipos DWORD y DWORD_PTR tienen diferentes tamaños. Entonces resulta que en el modo de 64 bits, las clases contienen dos funciones de WinHelp DIFERENTES, lo cual seguramente es incorrecto. Ten en cuenta que estas trampas pueden ocultarse no solo en MFC, donde algunas de las funciones ahora tienen otros tipos de argumentos, sino también en el código de sus aplicaciones y bibliotecas de terceros.

6.7. Diagnóstico de errores ocultos

Hay muchos ejemplos de este tipo de errores de 64 bits. Como puedes ver, la etapa de búsqueda de errores ocultos no es una tarea trivial y, además, muchos de ellos ocurrirán de manera irregular y solo con grandes entradas de datos. Los analizadores de código estático son buenos para diagnosticar tales errores, ya que pueden verificar todo el código de una aplicación independientemente de los datos de entrada y la frecuencia de ejecución de sus secciones en condiciones reales.

Tiene sentido utilizar el análisis estático tanto en la etapa de trasladar una aplicación a plataformas de 64 bits, para encontrar la mayoría de los errores desde el principio, como en el desarrollo posterior de soluciones de 64 bits. El análisis estático advertirá y enseñará a un programador a comprender mejor las peculiaridades de los errores relacionados con una arquitectura de 64 bits y a escribir código más eficiente.

Por justicia, deberíamos decir que los analizadores de código de prueba Gimpel PC-Lint y Parasoft C ++ tienen conjuntos de reglas para diagnosticar errores de 64 bits. Pero, en primer lugar, se trata de analizadores de uso general y las reglas para diagnosticar errores de 64 bits son incompletas. En segundo lugar, están pensados principalmente para el modelo de datos LP64 utilizado en la familia de sistemas operativos Linux, por lo que no son tan útiles para los programas de Windows en los que se utiliza el modelo de datos LLP64.

Paso 7: actualización del proceso de prueba

El paso de buscar errores en el código del programa descrito en la sección anterior es necesario, pero insuficiente. Ninguno de los métodos, incluido el análisis de código estático, puede garantizar la detección de todos los errores, y el mejor resultado se puede lograr solo cuando se combinan diferentes métodos.

Si tu programa de 64 bits procesa un tamaño de datos mayor que la versión de 32 bits, debes ampliar las pruebas para incluir el procesamiento de datos con un tamaño de más de 4 GB. Este es el límite más allá del cual comienzan a ocurrir muchos errores de 64 bits. Estas pruebas pueden llevar mucho más tiempo y debes estar preparado para ello.

Por lo general, las pruebas se escriben de tal manera que cada prueba pueda procesar una pequeña cantidad de elementos y, por lo tanto, hacer posible realizar todas las pruebas unitarias internas en varios minutos, mientras que las pruebas automáticas (por ejemplo, utilizando AutomatedQA TestComplete) podrían realizarse en varias horas.

Es casi seguro que la función de clasificación que clasifica 100 elementos se comportará correctamente en 100000 elementos en un sistema de 32 bits. Pero la misma función puede fallar en un sistema de 64 bits al intentar procesar 5 mil millones de elementos. La velocidad de ejecución de una prueba unitaria puede reducirse en millones de veces.

No te olvides del costo de adaptar las pruebas mientras dominas los sistemas de 64 bits. Una buena solución es dividir las pruebas unitarias en rápidas (que trabajan con tamaños de memoria pequeños) y lentas que procesan gigabytes y se ejecutan, por ejemplo, durante la noche. Las pruebas automatizadas de programas de 64 bits que consumen muchos recursos se pueden organizar sobre la base de cálculos distribuidos.

Advertencias

Hay una cosa más desagradable. Difícilmente tendrás éxito en el uso de herramientas como BoundsChecker para buscar errores en programas de 64 bits que consumen muchos recursos y consumen una gran cantidad de memoria. La razón es una gran ralentización de los programas que se están probando, lo que hace que este enfoque sea muy inconveniente.

En el modo de diagnosticar todos los errores relacionados con el funcionamiento de la memoria, la herramienta Parallel Inspector incluida en Intel Parallel Studio, ralentizará la ejecución de una aplicación 100 veces, en promedio. Es muy probable que tengas que dejar el algoritmo que se está probando durante la noche para ver los resultados solo al día siguiente, mientras que normalmente este algoritmo opera en solo 10 minutos.

Aun así, estamos seguros de que Parallel Inspector es una de las herramientas más útiles y convenientes cuando se trabaja en el modo de búsqueda de errores de operación de memoria. Solo necesitas estar preparado para cambiar la práctica del diagnóstico de errores y tenerlo en cuenta cuando planifiques dominar sistemas de 64 bits.

Diagnóstico de errores ocultos

Echa un vistazo a: 10 Mejores Herramientas De Reparación De Windows 10

Pensamientos finales

No olvides agregar pruebas que verifiquen la compatibilidad de los formatos de datos entre las versiones de 32 y 64 bits. La compatibilidad de datos a menudo se viola durante la migración, debido a la escritura de tipos como size_t o long (en sistemas Linux) en archivos. Esto ha sido todo nuestro tutorial sobre cómo transferir programas de 32 bits a 64 bits. Esperamos que hayas tenido una buena experiencia al momento de realizar el proceso.

Deja un comentario