2017-10-12 4 views
1

J'essaie de concaténer deux chaînes afin que je puisse obtenir un chemin de fichier. Cependant, je reçois une erreur dans valgrindC erreur Strcat valgrind

Saut conditionnel ou mouvement dépend de la valeur uninitialised (s)

Mon code:

/** 
* @brief Concatenate two strings to get file path 
* @param firstP - First string 
* @param secondP - Second string 
* @return Returns the concatenated string 
*/ 
char *getPathDir(char *firstP, char *secondP) { 
    char *new_str; 
    int stringSize = strlen(firstP)+strlen(secondP)+2; 

    if((new_str = malloc(stringSize)) != NULL){ 
     new_str[0] = '\0'; 
     strcat(new_str,firstP); 
     new_str[strlen(firstP)] = '/'; 
     strcat(new_str,secondP); 
    } else { 
     perror("malloc"); 
     cleanUp(); 
     exit(EXIT_FAILURE); 
    } 
    return new_str; 
} 
+5

'sprintf (new_str,"% s /% s ", premierP, secondP);' au lieu de. 'new_str [strlen (firstP)] = '/';' écrase le dernier null-terminator de la chaîne. Donc le 2ème 'strcat' ne trouve pas la fin de la chaîne correcte. – BLUEPIXY

+1

Il y a beaucoup mieux de faire cela ... fonction strcat. Voir: https://www.tutorialspoint.com/c_standard_library/c_function_strcat.htm ou suggestion @BLUEPIXY aussi :) –

+0

@BLUEPIXY J'ai tout enlevé de l'if-statement et l'ai remplacé par sprintf (new_str, "% s /% s" , premierP, deuxièmeP); ça fonctionne maintenant parfaitement. Merci :) – Cows42

Répondre

6

Regardons ces lignes:

new_str[0] = '\0'; 
    strcat(new_str,firstP); 
    new_str[strlen(firstP)] = '/'; 
    strcat(new_str,secondP); 

Avant d'écrire quoi que ce soit, la chaîne ressemble à ceci:

 +---+---+---+---+---+---+---+---+ 
    | ? | ? | ? | ? | ? | ? | ? | ? | 
    +---+---+---+---+---+---+---+---+ 

Après la première ligne (new_str[0] = '\0';), vous avez ceci:

 +---+---+---+---+---+---+---+---+ 
    | 0 | ? | ? | ? | ? | ? | ? | ? | 
    +---+---+---+---+---+---+---+---+ 

Après la deuxième ligne (strcat(new_str,firstP);), il ressemble à ceci:

 +---+---+---+---+---+---+---+---+ 
    | A | B | C | D | 0 | ? | ? | ? | 
    +---+---+---+---+---+---+---+---+ 

Maintenant, lorsque vous exécuter la ligne

new_str[strlen(firstP)] = '/'; 

vous écrasez le terminateur null et obtenez ceci:

 +---+---+---+---+---+---+---+---+ 
    | A | B | C | D |/| ? | ? | ? | 
    +---+---+---+---+---+---+---+---+ 

Ceci est un problème, parce que votre chaîne est plus nul fin, donc lors du prochain appel strcat le programme va commencer à lire dans la chasse de mémoire non initialisée autour de un terminateur null.

Si vous voulez concaténer les chaînes ensemble, il pourrait être plus facile à utiliser simplement sprintf, comme ceci:

sprintf(new_str, "%s/%s", firstP, secondP); 

Cette plus dit explicitement « écrire la première chaîne, puis le séparateur, puis la deuxième chaîne "et décharge toute la gestion de terminaison nulle dans la bibliothèque. Et les bibliothèques, à l'exception de strncat, traitent généralement bien les terminaisons NULL. :-)

Il est également possible que le sprintf soit légèrement plus rapide que ce que vous êtes en train de faire. En utilisant beaucoup de strcat s dans une rangée de la manière que vous proposez peut être inefficace en raison du overhead of rescanning the strings to find the null terminators, mais je ne parierais pas dessus. Il a, cependant, l'avantage très clair de communiquer plus précisément ce que vous essayez de faire, et les gains de lisibilité sont rarement une mauvaise chose.

+0

Excellente façon de présenter le problème. – Barmar

+0

Mais vous pouvez également montrer une solution simple qui ajoute le null nécessaire, ou utilise 'strcat (new_str,"/")' – Barmar

+0

@Barmar C'est vrai, mais pour des raisons de lisibilité, je pense que 'sprintf' est une meilleure option.Il y a aussi l'inefficacité (très négligeable) de rescanner les cordes encore et encore qui découle de l'utilisation de beaucoup de 'strcat's dans une rangée. – templatetypedef