2009-09-14 19 views
14

Estoy convirtiendo un extremadamente programa grande y muy viejo (25 años!) De C a C++.¡Accediendo a una matriz con un número negativo!

En ella hay muchos (muchísimos) lugares donde accedo a una matriz UBYTE unidimensional global usando una variedad de índices enteros. Ocasionalmente, este índice puede ser negativo.

A veces, pero no siempre, atrapé esta caja y me aseguré de que no pasara nada, pero como medida de correas y tirantes me tomé la molestia de asegurarme de que había otro trozo de memoria inmediatamente anterior a la matriz y llenaba con los valores correctos, de modo que si accidentalmente omití atrapar la condición numérica negativa, se obtendría una respuesta correcta en el acceso a la matriz. Esto realmente funcionó bien durante muchos años.

Pero ahora bajo C++ parece que acceder a una matriz con un número negativo se comporta de manera diferente y ahora tengo un programa que se comporta mal. Arreglé un caso de un número negativo no controlado y el programa parece estar funcionando bien, pero estoy nervioso de no haber atrapado todos los números negativos y puede haber problemas por delante.

Así que mi pregunta ahora es, ¿hay alguna forma, en tiempo de ejecución, para que detecte cualquier instancia de acceso a matrices con índices negativos? Estaré impresionado si alguien puede encontrar una respuesta. Si está seguro de que no se puede hacer de manera automática, entonces es una información valiosa.

Debo agregar que no soy realmente un programador de C++ (todavía). Hasta ahora, todo lo que he hecho es el mínimo absoluto (casi nada) para hacer que el programa se compile en un compilador de C++. Entonces, si su respuesta involucra a expertos "expertos solamente, soluciones de C++", intente y explique con palabras de una sílaba o déme un enlace para que pueda buscarlo.

+0

¡No pensé que pudiera acceder a una matriz con valor negativo! –

+0

Si funciona, no lo toques. –

+10

Si funciona, mejora. –

Respuesta

26

¿Se puede reemplazar la matriz ubyte unidimensional global por un objeto con operador sobrecargado []? Usar el valor absoluto de la entrada int puede resolver algunos de sus problemas.

Editar: Dependiendo del patrón de uso de su matriz (sin engaños del puntero), el uso de un objeto con operador sobrecargado [] podría ser completamente transparente para los usuarios de la matriz, de ahí mi sugerencia.

+5

Personalmente, lanzaría una excepción en lugar de usar el valor absoluto. (Falló temprano, falló alto. Usar el valor absoluto del índice simplemente continuaría el programa con un valor más o menos aleatorio.) – DevSolar

+0

Su comentario es correcto, aunque tenía la impresión de que la aplicación original había sido "pirateada" en el problema de índice negativo al duplicar el conjunto en la memoria alrededor de 0, dando el tipo de comportamiento con índices negativos que el valor absoluto podría hacer también. –

+0

como entiendo la pregunta, la versión original del programa hackeó alrededor, pero ahora él quiere ser notificado cuando se producen índices negativos, por lo que realmente puede * arreglar * el programa. Lo cual suena como el camino correcto a seguir. Y luego, por supuesto, una excepción sería correcta (aunque también podría ser útil registrarla y, probablemente, activar una afirmación) – jalf

2

la única forma en que puedo pensar sería envolver la matriz en un método que compruebe que el índice sea positivo.

4

Algún tipo de comprobador de uso de memoria podría funcionar, particularmente si puede forzar la matriz a su propia página. Yo usaría valgrind en Linux, no estoy seguro de qué usaría en Windows - purify?

+0

Normalmente sería el primero en promocionar valgrind para algo como esto, pero recientemente tuvimos exactamente este problema y no pudo encontrarlo. No conozco las partes internas de Valgrind, pero mi impresión es que solo detecta problemas de forma segura. –

3

Envuélvelo. Como alternativa, verifique si su compilador admite la verificación de límites. En el peor de los casos, no pondría valores válidos en su matriz en números negativos. Me gustaría poner descaradamentevalores incorrectos, por lo que se obtiene un valor claramente erróneo cuando esto ocurre. No señalará el problema sin un depurador, pero al menos tiene una advertencia clara de que en algún lugar, algún código lo está haciendo.

+0

¿Visual Studio 2008 admite la verificación de límites? – Mick

+0

No tengo idea, nunca usé VS, pero si no lo hace, entonces Microsoft tiene un problema. –

+0

El problema es que C (y C++ por extensión) definitivamente permiten el índice de matriz con un índice negativo, siempre y cuando no formes un índice fuera de la matriz (!). Por lo tanto, no puede simplemente hacer comprobaciones de límites, ni en Visual C++ ni en otros compiladores de C/C++. – MSalters

1

Personalmente, trataría de aclarar por qué alguno de sus índices podría ser negativo alguna vez; Es obvio que devolverán un valor incorrecto, por lo que seguramente no debería dejar que el índice sea negativo.

arreglar el código que les permite ser negativo en lugar de tratar de hacer un tapón en forma cuadrada en un agujero circular (por así decirlo);)

+0

1. El acceso a la matriz es súper rápido, por lo que soy reacio a incluirlo definitivamente en las llamadas a funciones. 2. De alguna forma, acceder a la matriz con números negativos tiene sentido lógico (en este dominio específico), por lo que permitiría que la solución original dudosa fuera mi respuesta favorita. – Mick

+0

Una de las cosas buenas de C++ es que los compiladores lo alinean muy agresivamente. Mientras todo esté visible para el compilador, las funciones pequeñas * se * incluirán, por lo que la sobrecarga es exactamente cero. No se preocupe demasiado por envolverlo en llamadas a funciones (siempre y cuando estén visibles las definiciones de funciones completas, no solo las declaraciones) – jalf

+0

Por cierto, esta información debe ir en la pregunta, donde todos la vean, no en un comentario . La pregunta da la impresión de que los índices negativos son errores que deben corregirse. Si se permiten índices negativos en su dominio problemático, háganoslo saber. Eso cambia la solución por completo. :) – jalf

3

¿Hay alguna manera, en tiempo de ejecución, para mí para detectar cualquier instancia de acceso a las matrices con índices negativos?

Reemplace su conjunto global por std::vector. Reemplazar el uso de la sintaxis array[index] por

vector.at(index) 

Esto hace exactamente lo que pide: se añade cheques con destino matriz en tiempo de ejecución.

0

Una cosa que puede hacer es verificar hasta qué valor mínimo van sus índices, y comenzar a llenar su matriz desde ese índice.

un [-i] = * (a - i)

así que empieza con (a-i) como su dirección de base en lugar de (a) por lo que sólo cambiar su matriz y obtener los valores deseados.

6

¿Conoces los límites de los índices?

Al leer el comentario bajo la respuesta de Siyfion, parece que los índices negativos están permitidos en el dominio de su problema, por lo que no tiene sentido tratar de forzar a todos los índices a ser positivos. Una mejor solución es permitir índices negativos sin romper ninguna regla de idioma (lo que también hizo tu versión C por cierto. Tuviste suerte de que no explotara;))

Así que si sabes que los índices que vas a el uso está en el rango -x a y, simplemente cree una matriz de tamaño x + y, y use un puntero al elemento xth cuando acceda a la matriz.

Por ejemplo, suponiendo que se necesita una matriz con índices de -4 a 5:

int arr[10]; 
int* ptr = arr+4; 
// use ptr when you need to index into the array: 

ptr[-4]; // is valid, reads arr[0] 
ptr[5]; // is valid, reads arr[9] 

Por supuesto, el mismo podría (y debería) se han hecho en C.

Otro consejo sería ser para no acceder directamente a la matriz en bruto. Definir funciones de acceso simples en su lugar. (por ejemplo, pero no necesariamente, al poner el conjunto en una clase. Si lo coloca en una clase, puede sobrecargar el operador [], por lo que incluso se verá como una matriz)

La sobrecarga de esto es precisamente cero (no "casi cero, o" tan cerca de cero que no notará la diferencia ", pero cero. El código generado será exactamente el mismo que si hubiera accedido directamente a la matriz), como el compilador inline funciones cortos, sino que también le permite insertar controles adicionales para que pueda verificar en versiones de depuración que nunca va más allá de los límites de la matriz

+0

solución simple pero elegante :) –

Cuestiones relacionadas