2016-07-11 1 views
1

Lors du débogage GDB me dit l'erreur suivante:C - ne peut pas accéder à la mémoire à l'adresse

0x800c99ed00000001 < error: Cannot access memory at address 0x800c99ed00000001> 

L'erreur est produit si je mets un point d'arrêt quand je l'appelle ConvertByteArrayToFloat pendant le débogage.

Mais le programme se termine sans problème et me donne un résultat Ok?

Mon fichier principal:

#include "Local.h" 

int main(void) { 

    if(HandleReceivedMessages() == OP_COMPLETED){ 
     printf("Main Completed \n"); 
    } else { 
     printf("Main Failed \n"); 
    } 
    return 0; 
} 

local.h

#ifndef LOCAL_H_ 
#define LOCAL_H_ 

#include "Common.h" 

T_OP_STATUS HandleReceivedMessages(void); 

#endif 

Local.c

#include "Handler.h" 
#include "Local.h" 

uint8_t message[] = {0x86, 0x9a, 0xa0, 0x00, 0x00, 0x01, 0x01, 0x07, 0x00, 0x10, 0x4a, 0x00, 0x00, 0x00, 0x00, 0xe1}; 

uint8_t length = 16; 

T_OP_STATUS HandleReceivedMessages(void) { 

    if(HandleResponseMessage(message, length) == STATUS_SUCCESS) { 
     printf("Completed from Local \n"); 
     return OP_COMPLETED; 
    } else { 
     printf("Failed from Local \n"); 
     return OP_FAILED; 
    } 

} 

Handler.h

#ifndef HANDLER_H_ 
#define HANDLER_H_ 

#include "Common.h" 

T_MESSAGE_STATUS HandleResponseMessage(uint8_t *requestData, uint8_t msgLength); 


#endif /* HANDLER_H_ */ 

Handler.c

#include "Handler.h" 
#include <string.h> 

static uint8_t rawRequestData[BUFFER_WIRED_SIZE]; 

static float TempFloat = 0; 


T_MESSAGE_STATUS HandleCmd(uint16_t cmdNumber, uint8_t rawDataLength, 
        uint8_t *rawDataPtr) { 

    switch (cmdNumber) { 
     case 1: 
      TempFloat = ConvertByteArrayToFloat(&rawDataPtr[3]); 
      printf("The value of the float is : %f \n", TempFloat); 
      return STATUS_SUCCESS; 
     default: 
      break; 
    } 

    return STATUS_NOT_IMPLEMENTED; 
} 


T_MESSAGE_STATUS HandleResponseMessage(uint8_t *message, 
           uint8_t msgLength) { 

    uint8_t cmdNumber, dataLength, startOfData; 


    // Check the delimiter. 
    if (message[0] & INDICATOR_UNIQUE_ADDRESS) { 

     cmdNumber = message[6]; 
     dataLength = message[7]; 
     startOfData = 8; 

    } else { 

     cmdNumber = message[2]; 
     dataLength = message[3]; 
     startOfData = 4; 
    } 

    // we copy only the real data from the command response 
    memcpy(&rawRequestData, message + startOfData, dataLength); 

    return HandleCmd(cmdNumber, dataLength, rawRequestData); 

} 

common.h

#ifndef COMMON_H_ 
#define COMMON_H_ 

#include <stdint.h> 
#include <stdio.h> 

#define BUFFER_WIRED_SIZE    128 
#define INDICATOR_UNIQUE_ADDRESS  0x80 


typedef enum { 

    OP_FAILED, 
    OP_COMPLETED, 

}T_OP_STATUS; 

typedef enum 
{ 
    STATUS_SUCCESS, 
    STATUS_NOT_IMPLEMENTED, 

} T_MESSAGE_STATUS; 

float ConvertByteArrayToFloat(uint8_t *data); 


#endif /* COMMON_H_ */ 

common.c

#include "Common.h" 

float ConvertByteArrayToFloat(uint8_t *data) { 

    union { 
     uint8_t tmpArray[4]; 
     float tmpFloat; 
    } value; 

    value.tmpArray[0] = data[3]; 
    value.tmpArray[1] = data[2]; 
    value.tmpArray[2] = data[1]; 
    value.tmpArray[3] = data[0]; 

    return value.tmpFloat; 
} 

Ceci est la version min, (il fait beaucoup de choses comme vérifier le format du message, CRC, etc ..) mais va du début à la fin à travers tous ces fichiers.

Je travaille sur une plate-forme embarquée et lors du débogage dans mon microcontrôleur et en appelant la fonction ConvertByteArrayToFloat, mon programme saute sur une autre partie de mon code puis il plante le microcontrôleur.

Je tente de recréer l'erreur sur mon ordinateur sans le microcontrôleur et j'ai trouvé l'erreur en haut.

+0

Quel est votre microcontrôleur? Est-ce big-endian ou little-endian? Vous avez besoin d'une fonction qui est l'inverse de 'ConvertByteArrayToFloat' (par exemple' ConvertFloatToByteArray'), qui n'est pas affichée, pour produire les messages que 'ConvertByteArrayToFloat' décode. Vous pouvez être câblé pour la mauvaise endianness et la fonction de conversion explose quand le flotteur est retourné. C'est-à-dire, câblé pour [dire] x86, donc ça marche, mais le contrôleur peut être big-endian [ou vice-versa] –

+0

Le micro est petit boutiste, mais le truc c'est que dans mon micro il ne touche pas le point de rupture ConvertByteArrayToFloat, quand il atteint cette déclaration, il saute à une autre partie non liée du code, puis il se bloque et passe dans HardFault. Oui, il y a aussi un ConvertFloatToByteArray, mais il n'est pas utilisé pour l'instant, puisque j'essaie juste de lire les valeurs et non de les écrire. – IzonFreak

+0

Semble UB causé par UB plus tôt. J'ai vu le '+ 3 'qui s'est déroulé [mais je pensais que vous aviez déjà vérifié cela]. Est-ce qu'il peut y avoir un autre endroit qui dépasse un tampon (c'est-à-dire qui vérifie le bureau) plus tôt qui cause ce problème plus tard? Stack overflow dû à une récursivité involontaire? Sur l'UC, pourrait interrompre les vecteurs [dont bkpt a besoin] être corrompu? Essayez un appel à la fonction de conversion au début init pour prouver que cela fonctionne au moins une fois. Ensuite, poivre les appels artificiels à lui tout (c'est à dire faire le canari dans la mine de charbon). Pouvez-vous _step_ le code (vs bkpt)? –

Répondre

2

Ce:

TempFloat = ConvertByteArrayToFloat(&rawDataPtr[3]); 

(où rawDataPtr est un argument uint8_t *) semble très suspect. Vous passez un pointeur sur le quatrième octet à rawDataPtr (identique à rawDataPtr + 3) à la fonction de conversion, qui lit ensuite quatre octets commençant à cet emplacement.

Cela ressemble à une sorte de confusion après avoir consommé les octets initiaux du message.

+0

Que rawDataPtr est la donnée envoyée dans le message, à partir de cet emplacement (3) je sais qu'il y a un flottant de 4 octets dans mon tableau de données (rawDataPrt) qui est ma valeur dans ce cas particulier que je veux extraire. Si vous voyez dans HandleResponseMessage, je copie simplement une partie spécifique du message en utilisant memcpy qui est mes données que je transmet ensuite à HandleCmd. – IzonFreak

+0

@IzonFreak Non, je ne vois pas ça. Je vois comment vous 'memcpy()' de l'octet 4 dans la source dans le 'rawData', mais alors vous sautez * un autre * quatre dans la ligne que j'ai cité, au moins c'est ma compréhension en ce moment. – unwind

+0

@IzonFreak J'ai bien peur d'être d'accord avec le déroulement. Donc, à partir du début absolu du buffer _raw_, le flottant est-il au décalage 4 ou 8? C'est-à-dire, quelle est la taille de l'en-tête qui doit être ignorée? Si l'en-tête est 4, alors le code devrait être '& rawDataPtr [0]'. Si cela doit être '& rawDataPtr [3]', _after_ la préconfiguration de 4/8 dans 'HandleResponseMessage', qu'y a-t-il dans' 0-3'? Peut-être, le moyen le plus simple est de l'essayer avec l'index 0 et de voir si UB s'en va. Ou, travaillez en arrière. Mettez le bkpt sur 'HandleCmd' ou' HandleReponseMessage' –