2010-06-16 9 views
7

Me gustaría cambiar mi aplicación a LARGEADDRESSAWARE. Uno de los problemas a tener en cuenta es la aritmética del puntero, ya que la diferencia del puntero ya no puede representarse como firmado 32b.Detecta aritmética de punteros debido a LARGEADDRESSAWARE

¿Hay alguna manera de encontrar automáticamente todas las instancias de resta de puntero en un gran proyecto de C++?

Si no, ¿hay algún método manual o semiautomático de "mínimo esfuerzo" para lograr esto?

+0

¿Quiere decir que está creando una aplicación para un sistema con un espacio de direcciones de 64 bits pero el compilador solo está utilizando punteros de 32 bits? –

+3

"LARGEADDRESSAWARE" es un indicador de Windows32 en un encabezado ejecutable, que le dice al sistema operativo que el ejecutable puede manejar direcciones de 32 bits. Sin él, obtendrá direcciones de 31 bits (es decir, el bit superior siempre es 0), y luego la segunda mitad del espacio de direcciones se reserva para el sistema operativo. – MSalters

Respuesta

0

Como nuestro código ya compila con GCC, creo que tal vez la forma más rápida podría ser:

  • construir un GCC
  • crear una modificación personalizada de GCC para que se imprima advertencia (o error) cada vez que el puntero la resta se detecta
  • construir el proyecto y recopilar todas las advertencias sobre la sustracción puntero

Aquí está el resumen de los cambios que se deben hacer para GCC para esto:

añaden sus advertencias en:

  • c-typeck.c (pointer_diff función)
  • cp/typeck.c (pointer_diff función).

Además de detectar directamente la resta del puntero, otra cosa que hacer puede ser detectar casos en los que primero se convierten punteros a tipos enteros y luego se restan. Esto puede ser más difícil dependiendo de cómo esté estructurado su código, en la búsqueda regexp en el caso de (.intptr_t). -. * - (. * Intptr_t) funcionó bastante bien.

0

Esto es solo un problema si tiene 2 punteros separados por más de 2000 millones de bytes (2 GB). Esto significa que:

  • o bien tienen matrices muy grandes (> 2 GB)
  • o está restando punteros que apuntan a diferentes estructuras totalmente

A fin de buscar estos casos especiales.

Creo que en la mayoría de los casos esto no es un problema.

+1

"o está restando punteros que apuntan a estructuras totalmente diferentes" - esto es algo que puede suceder fácilmente. En ocasiones, utilizamos punteros a los objetos como claves secundarias al ordenarlos para garantizar que el orden de clasificación sea estable. En cuanto a "buscar estos casos especiales", ¿cómo puedo buscarlos y luego revisar cada parte del código? – Suma

+0

Comparar los punteros no es un problema, restarlos es, y para el género, la comparación de los punteros debería ser suficiente. Además, no es una buena idea usar punteros como comparación final. Solía ​​hacer esto en el pasado también, pero esto podría dar problemas (los problemas pueden ser difíciles de reproducir ya que los indicadores pueden ser diferentes en cada ejecución de su aplicación; créanme, tuve este problema yo mismo varias veces). Intente encontrar otra característica (por ejemplo, un número de línea, una clave de base de datos, ...) para obtener una clasificación estable. – Patrick

+0

> "Comparar los punteros no es un problema, restarlos es," Desafortunadamente, al implementar la función de comparación para qsort, devolver la diferencia parece ser bastante natural, y ya lo he visto varias veces. Buen comentario, lamentablemente las preguntas principales aún no se responden - ¿cómo encontrar los casos? La base de código es enorme, es imposible encontrar todos los casos simplemente recordándolos. Se necesita un enfoque sistemático, ya sea automático o manual (revisión sistemática del código). La solución puede ser tiempo de compilación, una herramienta dedicada o tiempo de ejecución, con algunos instrumentos. – Suma

1

Compile el código con un compilador de 64 bits y Wp64 activado.

Debido a que los punteros son de 64 bits de ancho, pero int, long, etc. DWORD estancia de 32 bits de ancho, se obtiene advertencias para un cortocircuito ptrdiff_t a un int32_t

+2

Esta respuesta no es relevante, porque detecta problemas que pueden surgir si utiliza el tipo incorrecto para almacenar punteros, pero no le avisa si está haciendo comparaciones/restas de puntero "peligrosas". –

+0

Buena idea.No encontrará casos en los que la resta del puntero esté asignada a ptrdiff_t, aún esos casos también son un problema, ya que ptrdiff_t (int en Win32) no es suficiente para representar la diferencia del puntero, pero se pueden buscar mediante la búsqueda de texto para ptrdiff_t. El problema real es que hay demasiadas advertencias en el código, resolver cada una de ellas parece bastante trabajo y la gran mayoría de ellas no están relacionadas con LARGEADDRESSAWARE en absoluto (no tenemos intención de transferir el código a Win64). – Suma

+0

¿Afirma que hay un modo de compilación en el que ptrdiff_t no es lo suficientemente grande como para mantener la diferencia entre dos punteros? Eso suena ... bueno, simplemente roto, dado que esa es la definición estándar de ese tipo. (Esperaría que sea de un tamaño diferente en los diferentes modos de compilación). –

3

PC-pelusa puede encontrar este tipo de problema.

Mira http://gimpel-online.com/MsgRef.html, código de error 947:

operador Reste aplica a los punteros - Una expresión de la forma p - q se encontró que tanto p como q son punteros.Esto es de importancia especial en los casos en que el puntero máximo puede desbordar el tipo que contiene las diferencias de puntero. Por ejemplo, suponga que el puntero máximo es 3 Gigabytes -1 y que las diferencias de puntero están representadas por un largo, donde máximo largo es 2 Gigabytes -1. Tenga en cuenta que ambas cantidades se ajustan a dentro de una palabra de 32 bits. Luego, al restar un puntero pequeño de un puntero muy grande , se obtendrá un valor negativo aparente en el que representa la diferencia del puntero. Por el contrario, restando un puntero muy grande de un puntero pequeño puede producir una cantidad positiva.

Cuestiones relacionadas