0

所以我的代码中出现了段错误,我似乎无法弄清楚是什么原因造成的。有没有人能够捕捉到我没有捕捉到的东西?

从逻辑上讲,我试图通过将事物连接到末尾来创建一个 char 数组(一个字符串),然后将其添加到一个字符串数组中。

它最终应该是这样的'word1,word2,word3,word4,word5 ...等'

段故障发生在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 堆栈跟踪:

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

有谁知道为什么会发生这种情况?

4

3 回答 3

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;
}
于 2012-12-09T09:12:12.217 回答
1

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

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

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

    最后调整你str的大小strlen(str) + 1,以免浪费内存。

于 2012-12-09T09:24:11.923 回答
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

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

于 2012-12-09T13:42:25.563 回答