我正在尝试连接两个字符串,以便我可以获取文件路径.但是,我在valgrind中收到错误
条件跳转或移动取决于未初始化的值
我的代码:
/**
* @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;
}
Run Code Online (Sandbox Code Playgroud)
我们来看看以下几行:
new_str[0] = '\0';
strcat(new_str,firstP);
new_str[strlen(firstP)] = '/';
strcat(new_str,secondP);
Run Code Online (Sandbox Code Playgroud)
在写任何东西之前,字符串看起来像这样:
+---+---+---+---+---+---+---+---+
| ? | ? | ? | ? | ? | ? | ? | ? |
+---+---+---+---+---+---+---+---+
Run Code Online (Sandbox Code Playgroud)
在第一行(new_str[0] = '\0';)之后,你有这个:
+---+---+---+---+---+---+---+---+
| 0 | ? | ? | ? | ? | ? | ? | ? |
+---+---+---+---+---+---+---+---+
Run Code Online (Sandbox Code Playgroud)
在第二行(strcat(new_str,firstP);)之后,它看起来像这样:
+---+---+---+---+---+---+---+---+
| A | B | C | D | 0 | ? | ? | ? |
+---+---+---+---+---+---+---+---+
Run Code Online (Sandbox Code Playgroud)
现在,当你执行该行
new_str[strlen(firstP)] = '/';
Run Code Online (Sandbox Code Playgroud)
你覆盖null终止符并得到这个:
+---+---+---+---+---+---+---+---+
| A | B | C | D | / | ? | ? | ? |
+---+---+---+---+---+---+---+---+
Run Code Online (Sandbox Code Playgroud)
这是一个问题,因为你的字符串不再是以null结尾的,所以当你下次调用时strcat,程序将开始读取未初始化的内存,寻找一个空终止符.
如果要将字符串连接在一起,可能更容易使用sprintf,如下所示:
sprintf(new_str, "%s/%s", firstP, secondP);
Run Code Online (Sandbox Code Playgroud)
这更明确地说"写第一个字符串,然后是分隔符,然后是第二个字符串",并将所有空终止符管理卸载到库中.除了库之外,库strncat通常很好地处理空终止符.:-)
也有sprintf可能比你正在做的更快.strcat由于重新扫描字符串以找到空终止符的开销,以你提议的方式连续使用大量的s可能是低效的,但我不打赌它.但是,它确实具有更明确的优势,可以更准确地传达您正在尝试做的事情,并且可读性获胜很少是一件坏事.