我正在尝试连接两个字符串,以便获取文件路径。但是,我在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;
}
答案 0 :(得分:6)
让我们来看看这些内容:
new_str[0] = '\0';
strcat(new_str,firstP);
new_str[strlen(firstP)] = '/';
strcat(new_str,secondP);
在写任何东西之前,字符串看起来像这样:
+---+---+---+---+---+---+---+---+
| ? | ? | ? | ? | ? | ? | ? | ? |
+---+---+---+---+---+---+---+---+
在第一行(new_str[0] = '\0';
)之后,你有这个:
+---+---+---+---+---+---+---+---+
| 0 | ? | ? | ? | ? | ? | ? | ? |
+---+---+---+---+---+---+---+---+
在第二行(strcat(new_str,firstP);
)之后,它看起来像这样:
+---+---+---+---+---+---+---+---+
| A | B | C | D | 0 | ? | ? | ? |
+---+---+---+---+---+---+---+---+
现在,当你执行
行时 new_str[strlen(firstP)] = '/';
你覆盖了null终结符并得到了这个:
+---+---+---+---+---+---+---+---+
| A | B | C | D | / | ? | ? | ? |
+---+---+---+---+---+---+---+---+
这是一个问题,因为你的字符串不再以空值终止,所以当你下次调用strcat
时,程序将开始读取未初始化的内存,寻找空终止符。
如果要将字符串连接在一起,可能更容易使用sprintf
,如下所示:
sprintf(new_str, "%s/%s", firstP, secondP);
这更明确地说"写第一个字符串,然后是分隔符,然后是第二个字符串"并将所有空终止符管理卸载到库中。除了strncat
之外,库通常很好地处理空终止符。 : - )
sprintf
也可能比你正在做的事情稍微快一点。由于overhead of rescanning the strings to find the null terminators,以你提出的方式连续使用大量strcat
s可能效率低下,但我不打赌它。但是,它确实具有更明确的优势,可以更准确地传达您正在尝试做的事情,并且可读性获胜很少是坏事。