2015-08-03 1 views
-1

J'utilise this library for libgps et j'ai quelques problèmes pour le faire fonctionner correctement.Segfault jeté sur une ligne de code

L'erreur de mon débogueur après qu'il dit segfault est:

Cannot find bounds of current function 

La ligne de code est ce lancer located in this file, en ligne 132.

uint8_t checksum= (uint8_t)strtol(strchr(message, '*')+1, NULL, 16); 

Je ne connais pas le contexte de cette du tout, et je ne sais pas pourquoi cela ne ferait pas de segfault.

Mon code:

#include <stdio.h> 
#include <stdlib.h> 
#include <gps.h> 
#include <math.h> 

/* 
* 
*/ 
int main(int argc, char** argv) { 

    // Open 
    gps_init(); 
    gps_on(); 

    loc_t data; 

    gps_location(&data); 
    printf("%lf %lf\n", data.latitude, data.longitude); 

    return (EXIT_SUCCESS); 
} 

La fonction gps_location() vous emmène dans gps.c et de là elle se heurte serial.c, une fois qu'il court:

void serial_readln(char *buffer, int len) 
{ 
    char c; 
    char *b = buffer; 
    int rx_length = -1; 
    while(1) { 
     rx_length = read(uart0_filestream, (void*)(&c), 1); 

     if (rx_length <= 0) { 
      //wait for messages 
      sleep(1); 
     } else { 
      if (c == '\n') { 
       *b++ = '\0'; 
       break; 
      } 
      *b++ = c; 
     } 
    } 
} 

Sur le break retourne à gps.c va dans:

switch (nmea_get_message_type(buffer)) { 

qui le prend en nmea.c pour nmea_get_message_type ci-dessus.

Il passe ensuite la ligne:

if ((checksum = nmea_valid_checksum(message)) != _EMPTY) 

le prendre jusqu'à: uint8_t checksum= (uint8_t)strtol(strchr(message, '*')+1, NULL, 16); qui est où l'erreur est.

À quoi est-ce dû?

Edit:

uint8_t est défini comme: typedef unsigned char uint8_t;

+0

S'il n'y a pas ' '*'' dans la chaîne, 'strchr()' 'rendement null', qui' strtol() 'est pas conçu pour gérer. Ajoutez une vérification de 'NULL' avant de passer le résultat de' strchr() 'à' strtol() '. – EOF

+0

Je ne vois pas assez de code pour savoir si cela contribue à votre problème, mais 'serial_readln()' 'ne tient pas compte len', donc pourrait être écrit après la fin de' buffer'. Je le réparerais dans tous les cas, pour lever tout doute. – donjuedo

+0

@MattMcNabb ce n'est pas mon code - je ne trouve pas de bibliothèques fiables et à jour pour une utilisation avec GPSD (GPD Deamon). Je pense que le message étant nul est la bonne réponse ici. Ma connaissance de la programmation est loin d'assez bon pour faire ma propre bibliothèque pour ce genre de chose –

Répondre

0

Segmentation fault est pas « jeté exception » en tant que tel, il est un problème émis matériel ("vous avez dit y aller, mais je n » t voir quelque chose nommé «là»). En ce qui concerne votre problème: que se passe-t-il lorsque le strchr() ne trouve pas le caractère spécifié? Je vous suggère de l'essayer et de le découvrir.

+1

Merci pour l'entrée, j'ai eu un coup d'œil à la fonction 'strchr', et de ce que je peux voir qu'il prend deux args, on est une chaîne et l'autre est le paramètre de recherche? Donc, dans ce cas, il recherche la variable 'message' pour un' * '? Le contenu de 'message' à ce stade est:' 0 '\\ 000'', je n'ai aucune idée de ce que c'est –

+1

@ IGarratt cela signifie que 'message' pointe vers une chaîne vide, donc votre code provoque [comportement indéfini] (http://stackoverflow.com/a/4105123/1505939) car 'strchr' retournera un pointeur nul. –

+1

@MattMcNabb merci pour cela, ce code est criblé de bugs. '* b ++ = c;' est en dehors des limites dans 'serial_readln' –

0

Le code avec lequel vous travaillez est horrible et n'a aucune vérification d'erreur nulle part. Donc, il peut aller haywire pour toute entrée inattendue. Cela pourrait aussi être une vulnérabilité de sécurité potentielle.

Pour résoudre ce cas particulier, modifiez le code:

if (!message) 
    return NMEA_CHECKSUM_ERR; // possibly `exit` or something, this shouldn't happen 

char *star = strchr(message, '*'); 
if (!star) 
    return NMEA_CHECKSUM_ERR; 

uint8_t checksum = strtol(star, NULL, 16); 

Le nmea_parse_gpgga et nmea_parse_gprmc ont également plusieurs instances d'un problème similaire.

Ces fonctions peuvent être acceptables s'il existe un analyseur ou une vérification d'expression rationnelle qui nettoie l'entrée avant d'appeler ces fonctions. Cependant, en fonction de votre question (je n'ai pas vérifié la base de code), il semble que les données sont passées directement de read ce qui est inexcusable.

La fonction segfaulting n'a pas été conçu pour traiter un message vide ou, en fait, aucun message ne correspond pas à la forme prévue.

Une autre erreur désastreuse est que la fonction serial_readln ne vérifie jamais qu'elle n'écrit pas au-delà de len.

+0

Merci pour cela - vous avez résolu la moitié du problème ici ! Ce qui est comme vous dites aucune erreur de vérification au cas où il ne se comporte pas comme prévu. Je pense que le problème fondamental est que 'serial_readln' va « hors limites » en quelque sorte, en donnant l'erreur dans le débogueur pour la variable b' 0xbf000000 ', il est donc pas vraiment arriver à la' strchr' peu en premier lieu. Quelle horrible bibliothèque. Je ne l'emploierais pas s'il y avait des alternatives autour de –

+0

@IGarratt essaye de fixer 'serial_readln' pour abandonner quand il a lu les caractères' len - 1'. Le code appelant est 'char buffer [256];' de sorte que ça ne puisse pas vraiment aller mal –