strtok() 与 realloc() 奇怪的行为

strtok() with realloc() weird behaviour

我有以下用 C 语言编写的程序:

    ...
    char *answer = NULL;
    char *pch = strtok(phrase, " "); // phrase is a string with possibly many words
    while (pch) {
        char *tmp = translate_word(pch); // returns a string based on pch
        void *ptr = realloc(answer, sizeof(answer) + sizeof(tmp) + 1000); // allocate space to answer
        if (!ptr) // If realloc fails
             return -1;
        strcat(answer, tmp); // append tmp to answer
        pch = strtok(NULL, " "); // find next word
    }
    ...

问题是 strtok() 表现出奇怪的行为,它 returns 一个不存在于 短语 字符串中但属于 answer 字符串。

另一方面,当我更改以下行时:

void *ptr = realloc(answer, sizeof(answer) + sizeof(tmp) + 1000);

至:

void *ptr = realloc(answer, sizeof(answer) + sizeof(tmp) + 1);

strok() 按预期工作。

在这种情况下,realloc() 怎么可能影响 strtok()?他们甚至不使用相同的变量。期待您的见解。

realloc函数可以移动之前分配的内存。调用后,指向已分配内存的指针被 returned,传递给它的指针值如果不同,则不再有效。因此,当您调用 strcat(answer, tmp); 时,您可能正在写入调用 undefined behavior 的已释放内存,在这种情况下,它表现为您看到的奇怪输出。

检查 realloc 的 return 值后,将该值重新分配给 answer

另外,sizeof(answer)sizeof(tmp) 给你的是指针的大小,而不是它指向的对象的大小。您反而想使用 strlen 来获取字符串的长度然后包含。当我们这样做的时候,让我们只加 1 而不是 1000 因为这就是你真正需要的。

    void *ptr = realloc(answer, strlen(answer) + strlen(tmp) + 1);
    if (!ptr)
         return -1;
    answer = ptr;
    strcat(answer, tmp);

还有一个问题:第一次realloc调用内存完全未初始化。随后对其调用 strcat 取决于 answer 包含一个空终止字符串。事实并非如此,这也会调用未定义的行为。

这可以通过 malloc-ing 单个字节开始并将其设置为 0 来解决,这样你就可以从一个空字符串开始。

char *answer = malloc(1);
if (!answer) return -1;
answer[0] = 0;

sizeof(answer) & sizeof(tmp) 给出指针的大小。

您需要改用 strlen

另外...

char *answer = NULL;

...要么:

... strlen(answer) ...
strcat(answer, tmp);

这些应该会失败,出现分段冲突,但可能不会,这取决于 OS。取消引用 NULL 从来都不是一个好主意。

简而言之,您需要知道您已将某些内容分配给 answer,或者检查答案是否为 NULL。