Pregunta

Actualmente estamos desarrollando una aplicación para una MCU msp430 y nos encontramos con algunos problemas extraños.Descubrimos que declarar matrices dentro de un alcance después de la declaración de variables "normales", a veces causa lo que parece ser un comportamiento indefinido.Como esto:

foo(int a, int *b);

int main(void)
{
    int x = 2;
    int arr[5];

    foo(x, arr);

    return 0;
}

A foo se le pasa un puntero como segunda variable, que a veces no apunta a la llegar formación.Verificamos esto con un solo paso por el programa y vemos que el valor de la variable arr array-as-a-pointer en el alcance principal no es el mismo que el valor de la variable de puntero b en el alcance foo.Y no, esto no es realmente reproducible, sólo hemos observado este comportamiento de vez en cuando.

Esto es observable incluso antes de que se ejecute una sola línea de la función foo, el parámetro de puntero pasado (b) simplemente no apunta a la dirección que es arr.

Cambiar el ejemplo parece resolver el problema, así:

foo(int a, int *b);

int main(void)
{
    int arr[5];
    int x = 2;

    foo(x, arr);

    return 0;
}

¿Alguien tiene alguna aportación o sugerencia sobre por qué experimentamos este comportamiento?¿O experiencias similares?La guía de programación MSP430 especifica que el código debe cumplir con la especificación ANSI C89.Entonces me preguntaba si dice que las matrices deben declararse antes que las variables que no son matrices.

Se agradecería cualquier aportación al respecto.


Actualizar

@Adam Shiemke y tomlogic:

Me pregunto qué especifica C89 sobre las diferentes formas de inicializar valores dentro de las declaraciones.¿Se le permite escribir algo como:

int bar(void)
{
    int x = 2;
    int y;

    foo(x);
}

Y si es así, ¿qué pasa con:

int bar(int z)
{
    int x = z;
    int y;

    foo(x);
}

eso está permitido?Supongo que lo siguiente debe ser ilegal C89:

int bar(void)
{
    int x = baz();
    int y;

    foo(x);
}

Gracias de antemano.


Actualización 2Problema resuelto.Básicamente deshabilitamos las interrupciones antes de llamar a la función (foo) y después de las declaraciones de variables.Pudimos reproducir el problema en un ejemplo simple, y la solución parece ser agregar una declaración _NOP() después de desactivar la llamada de interrupción.

Si alguien está interesado, puedo publicar el ejemplo completo que reproduce el problema y la solución.

Gracias por todos los aportes sobre esto.

¿Fue útil?

Solución

debe ser capaz de determinar si se trata de un error del compilador basado en el código de montaje que se produce. Es el conjunto diferente cuando se cambia el orden de las declaraciones de variables? Si el depurador que permite, trate paso a paso a través del conjunto.

Si usted encuentra un error del compilador, también, comprobar su optimización. He visto errores como éste introducido por el optimizador.

Otros consejos

que se parece a un error del compilador.

Si usted utiliza su primer ejemplo (la problemática) y escribe su llamada a la función como foo(x, &arr[0]);, ¿ves los mismos resultados? ¿Qué pasa si usted inicializar la matriz como int arr[5] = {0};? Ninguno de estos debe cambiar nada, pero si lo hacen sería hacer alusión a un error del compilador.

En su pregunta actualización:

  

Básicamente, donde deshabilitar interrupciones antes de llamar a la función (foo) y después de las declaraciones de variables. Nosotros cuando sea capaz de reproducir el problema en un ejemplo sencillo, y la solución parece ser la de añadir una declaración _NOP() después de la llamada de interrupción desactivar.

Parece como si la interrupción desactivación intrínseca función / / macro (o sin embargo las interrupciones están deshabilitadas) podría ser la causa de una instrucción para ser 'saltado' o algo así. Me investigar si se codifica / trabajar correctamente.

Los dos ejemplos parecen ser conformes C89 a mí. No debería haber ninguna diferencia observable en el comportamiento suponiendo que foo no está accediendo a más allá de los límites de la matriz.

Para C89, las variables deben ser declaradas en una lista en el inicio del alcance antes de cualquier asignación. C99 le permite mezclar asignación de una declaración. Por lo tanto:

{ 
    int x; 
    int arr[5];

    x=5;
...

es el estilo c89 legal. Me sorprende su compilador no tiró algún tipo de error en el que si no es compatible con C99.

Suponiendo que el código real es mucho más compleja, Heres algunas cosas que me gustaría comprobar, tenga en cuenta que son conjeturas:

Podría ser desbordado la pila en alguna ocasión? Si es así este podría ser un artefacto de la "defensa de pila" por el compilador / UC? ¿El valor incorrecto de caída y foo dentro de un rango de memoria predecible? si es así qué ese rango tiene ningún significado (dentro de la pila, etc.)?

¿El mcu430 tienen diferentes rangos de RAM y ROM abordar? Es decir, es el espacio de direcciones de 16 bits de memoria RAM, mientras que el espacio de direcciones del programa de 24 bits? de PIC tienen tal arquitectura por ejemplo. Si es así, sería factible que arr está siendo asignado como ROM (de 24 bits) y la función espera un puntero a la RAM (16 bits) el código funcionaría cuando el arr fue asignada en la primera de 16 bits de espacio de direcciones pero de ladrillo si es por encima de ese rango .

Tal vez usted tiene en algún lugar en su programa de escritura de memoria ilegal que corrompe su pila.

¿Ha tenido una mirada en el desmontaje?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top