2017-08-23 2 views
-1

J'ai 3 problèmes mais je pense qu'ils sont essentiellement les mêmes.C - 3 problèmes avec la segmentation faute quand essayer de retourner la chaîne

J'ai 3 fonctions qui font quelque chose sur la chaîne qu'ils obtiennent en tant que paramètre, mais quand j'essaye de renvoyer le résultat, j'obtiens une faute de segmentation à chaque fois et je ne peux pas comprendre pourquoi.

/* the function gets a string, and return the string without blank spaces (is exists) in the end of the string */ 
char *trimRightSpaces(char *str, unsigned int len) 
{ 
    unsigned int i = len; 
    char *trimStr = NULL; 

    if(str == NULL) 
     return NULL; 

     while(i > 0) 
    { 
     if(isspace((int)str[i])) 
        break; 
     i--; 
    } 

    strncpy(trimStr, str, i-1); 
    trimStr[i+1] = '\0'; 
    return trimStr; 
} 

et cette fonction obtient des étiquettes de mon programme, qui ne sont que des chaînes avec caractère ':' à la fin:

/* The function gets a pointer to a string, and returns the name of label without ':' if it's a valid label, NULL if not. */ 
char *isLabel(char *str) 
{ 
    int i; 
    char tempStr[80]; 

    if(str == NULL) 
     return NULL; 

    if(strlen(str) > VALID_LABEL_LENGTH) 
     return NULL; 

    for(i = 0; i < strlen(str); i++) 
    { 
     if(i == 0) 
     { 
      /* if the first letter of the string is not small or capital letter, then it's not a valid label. */ 
      if(!isalpha((int)str[0])) 
       return NULL; 
     } 

     if(i == (strlen(str) - 1)) 
     { 
       if((int)str[i] != ':') /* check it the word ends with ':', otherwise it's not a valid label */ 
        return NULL; 
       break; 
     } 

     if(!isalnum((int)str[i])) 
      return NULL; 
    } 

    strncpy(tempStr, str, strlen(str) - 1); 

    if(isLanguageWord(tempStr)) 
     return NULL; 

    return str; 
} 

et:

/* the function get a string, and check if it's a valid string: a string inside " ". if it's valid, it returns the string without " ", and NULL otherwise. */ 
char *validString(char *str) 
{ 
    char temp[80]; 
    char *temp2 = NULL; 
    int i; 

    if(str == NULL) 
     return NULL; 

    if(str[0] != '"' || str[strlen(str) - 1] != '"') 
     return NULL; 

    for(i = 1; i < strlen(str) - 1; i++) 
    { 
     temp[i] = str[i]; 
    } 
    temp2 = temp; 
    return temp2; 
} 
+4

Où diantre est la mémoire allouée pour 'trimStr' dans votre premier extrait? – Bathsheba

+2

Dans le premier, il n'y a pas de chaîne. Il n'est pas alloué, juste un pointeur NULL. Paresseux pour passer le reste, mais évidemment vous avez besoin de réviser ce que vous savez sur le travail avec des pointeurs. –

+3

'char * trimStr = NULL; ... strncpy (trimStr, str, i-1); '-> Tenter d'écrire des données dans un emplacement invalide. – chux

Répondre

1

dans la fonction:

char *validString(char *str) 

cette déclaration:

temp2 = temp; 

définit le pointeur pour pointer vers une variable locale.

Puis cette déclaration:

return temp2; 

est de retour ce pointeur.

Le problème est lorsque la variable locale « est hors de portée » (ce qui arrive lorsque la fonction se termine.) Que pile variable ne plus est utilisable.

accéder au contenu de cette variable dans la fonction d'appel est un comportement non défini.

I.E. la fonction peut être réduite à:

/* the function get a string, and check if it's a valid string: a string inside " ". if it's valid, it returns the string without " ", and NULL otherwise. */ 
char *validString(char *str) 
{ 
    if(str == NULL) 
     return NULL; 

    if(str[0] != '"' || str[strlen(str) - 1] != '"') 
     return NULL; 

    return strdup(str); 
} // end function: validString 

la fonction: trimRightSpaces() ne fait pas couper les espaces de fuite et a le même problème que la fonction validString(). Proposer:

/* the function gets a string, and return the string without blank spaces (is exists) in the end of the string */ 
char *trimRightSpaces(char *str) 
{ 
    if(str == NULL) 
     return NULL; 

    size_t i; 
    for(i = strlen(str); i > 0 && ' ' == str[i]; i--); 

    char *trimstr = strdup(str); 

    if(trimstr) 
     trimstr[i] = '\0'; // note: this may need to be [i+1] 

    return trimstr; 
} // end function: trimRightSpaces 

la fonction: islabel() a le même problème et quelques autres problèmes. Suggestion:

/* The function gets a pointer to a string, and returns the name of label without ':' if it's a valid label, NULL if not. */ 
char *isLabel(char *str) 
{ 
    if(str == NULL) 
     return NULL; 

    if(strlen(str) > VALID_LABEL_LENGTH) 
     return NULL; 

    if(isLanguageWord(str)) // note: this 'may' not work, but function not posted so don't know 
     return NULL; 

    if(str[strlen(str) -1] != ':') /* check it the word ends with ':', otherwise it's not a valid label */ 
     return NULL; 

    /* if the first letter of the string is not small or capital letter, then it's not a valid label. */ 
    if(!isalpha((int)str[0])) 
     return NULL; 

    for(size_t i = strlen(str); i ; i--) 
    { 
     if(!isalnum((int)str[i])) 
      return NULL; 
    } 

    return strdup(str); 
} // end function: isLabel 
+0

Note: cette ligne:' pour (i = strlen (str); i> 0 && '' == str [i]; i--); 'suppose qu'il y ait (au moins) un caractère non espace dans la chaîne. – user3629249

+0

vous devrez libérer les chaînes par ces fonctions – pm100

0

Il existe différents problèmes dans votre code.

Par exemple, si vous pointeur declate à CHAR

char *trimStr = NULL; // Points to NULL, cant dereference 
char *trimStr;   // Uninitialized ptr, cant dereference 

alors vous ne pouvez pas déréférencer NULL ou pointeur non initialisé. Quoi de pire que vous essayez de copier des données à l'intérieur. Ce que vous devez faire est d'allouer suffisamment de mémoire sur tas, par exemple

char *trimStr = malloc(len); 

Ensuite, vous pouvez copier len octets dans trimStr. Deuxièmement, vous ne pouvez pas retourner le pointeur sur une variable locale comme dans validString car après que le compteur de programme est revenu de la fonction, la trame est détruite et la variable locale est hors de portée -> plus accessible.Vous devez retourner le pointeur sur la mémoire allouée sur le tas ou passer un pointeur sur le tableau à la fonction, où vous allez remplir ce tableau.

Aussi je peux voir quelques logiques problèmes comme

if(isspace((int)str[i])) 

Si vous voulez couper des espaces, mais isspace renvoie une valeur non nulle si son espace. Vous devez donc nier l'expression

if(!isspace((int)str[i])) 

Here is the example of trimRightSpaces function.