【问题标题】:C Strcat valgrind errorC Strcat valgrind 错误
【发布时间】:2017-10-12 23:35:25
【问题描述】:

我正在尝试连接两个字符串,以便获得文件路径。但是,我在 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;
}

【问题讨论】:

  • sprintf(new_str, "%s/%s", firstP, secondP); 而不是。 new_str[strlen(firstP)] = '/'; 覆盖字符串的最后一个空终止符。所以第二个strcat 找不到正确字符串的结尾。
  • 有更好的方法来做到这一点...... strcat 函数。请参阅:tutorialspoint.com/c_standard_library/c_function_strcat.htm 或 @BLUEPIXY 建议:)
  • @BLUEPIXY 我删除了 if 语句中的所有内容并将其替换为 sprintf(new_str, "%s/%s", firstP, secondP);它现在完美无缺。谢谢:)

标签: c string strcat


【解决方案1】:

让我们看看这些行:

    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)] = '/';

你覆盖空终止符并得到这个:

     +---+---+---+---+---+---+---+---+
     | 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,以您提议的方式连续使用大量strcats 可能效率低下,但我不会打赌。但是,它确实具有非常明显的优势,可以更准确地传达您正在尝试做的事情,并且赢得可读性并不是一件坏事。

【讨论】:

  • 提出问题的好方法。
  • 但您也可以展示一个简单的解决方案,添加必要的 null,或使用 strcat(new_str, "/")
  • @Barmar 没错,但为了便于阅读,我认为sprintf 是一个更好的选择。连续使用大量strcats 会导致一遍又一遍地重新扫描字符串(非常微不足道)效率低下。
  • 虽然sprintf() 确实是“正确”的做法,但出于教育目的,它可以帮助显示需要在幕后完成的工作。
  • @templatetypedef 解释得很好!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-28
  • 1970-01-01
  • 2020-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多