strcat上的段错误

时间:2012-12-09 08:53:30

标签: c strcat

所以我在我的代码中遇到了一个seg错误,而我似乎无法弄清楚导致它的原因。有人能抓到我不喜欢的东西吗?

逻辑上我正在尝试通过连接到最后的东西来创建一个char数组(一个字符串),然后将它添加到一个字符串数组中。

它应该最终看起来像'word1,word2,word3,word4,word5 ......等'

seg错误发生在strcat(str, ", ");

void save_ladder(graphNode *curNode) {

    char *str = malloc(1000 * sizeof(char));

    strcpy(str, "");
    strcat(str, curNode->word);
    strcat(str, ", ");

    graphNode *prev = curNode->prevWord;
    while (prev != NULL) {
            if (prev->prevWord != NULL) {
                strcat(str, prev->word);
                strcat(str, ", "); // SEG FAULT HAPPENS HERE
            }
            else 
                strcat(str, prev->word);

            prev = prev->prevWord;
    }

    ladders[numLadders++] = str;
}

gdb stacktrace:

Program received signal SIGSEGV, Segmentation fault.
0x00000000004013d1 in save_ladder (curNode=0x6420f0) at wordladder.c:150
150             strcat(str, ", ");

有谁知道为什么会这样?

3 个答案:

答案 0 :(得分:3)

可能是缓冲区溢出。将以下代码放在while循环中,并检查是否是这种情况:

printf ("%d %d\n", strlen (str), strlen (prev->word));

如果这两个数字的总和接近1000,那么你的缓冲区可能需要更大。

或者,如果第二个似乎有点大或看起来有太多单词,那么列表中的数据或列表结构本身都是可疑的。

此外,还有另外两点。第一个是你永远不需要乘以sizeof(char),因为它总是1(你也应该检查malloc的返回值,以防它失败)。

第二个是你可以简化你的字符串构造,而if中没有while语句:

strcpy(str, curNode->word);
graphNode *prev = curNode->prevWord;
while (prev != NULL) {
    strcat (str, ", ");
    strcat(str, prev->word);
    prev = prev->prevWord;
}

答案 1 :(得分:1)

我有两件事要注意/评论/回复:

  1. 您正在使用Schlemiel the Painter的算法:在每个strcat()上,到目前为止收集的字符串将再次遍历。您应该考虑使用"光标指针"指向您当前所在的位置:将每个strcat(str, ...)替换为strcpy(crsr, ...)后跟crsr += strlen(crsr),以便将其设置为字符串到目前为止的末尾。 crsr应该在开始时设置为str

  2. 正如其他人所写,您的代码最多只能使用1000个字符。您的结构要么坏了,要么其中一个字符串太长。无论如何,你的算法太不灵活了。您应该考虑在追加之前检查每个字符串长度,如果它不合适,realloc()适当地str。 (不要忘记更新你的crsr。)在这种情况下,你不再有任何限制。

    str的结尾调整为strlen(str) + 1,以免浪费内存。

答案 2 :(得分:1)

我同意缓冲区溢出答案。我也同意代码清理。但是,我想也许你应该研究asprintf或snprintf。使用asprintf,您提供char **并返回新字符串的位置。如果您不需要自己仔细管理内存,这将非常有用。此例程也是GNU扩展,因此请注意。 Snprintf允许您传递char *和剩余缓冲区的长度,以确定其余格式是否合适。这将抓住溢出。

以下是使用asprintf的示例:

char *output = NULL;
char *last = NULL;

prev = curNode;
while (prev != NULL) {
    last = output;
    if (asprintf(&output, "%s,", prev->word) < 0) {
        break;  // error
    }
    if (last != NULL)
        free(last);
    }
    prev = prev->prevWord;
}

// remove trailing ',' here

注意:上面的代码没有经过测试(我在平板电脑上写这个。)