我有以下用 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
}
...
Run Code Online (Sandbox Code Playgroud)
问题是 strtok() 表现出奇怪的行为,它返回一个词,该词不存在于短语字符串中,但属于答案字符串的一部分。
另一方面,当我更改以下行时:
void *ptr = realloc(answer, sizeof(answer) + sizeof(tmp) + 1000);
Run Code Online (Sandbox Code Playgroud)
到:
void *ptr = realloc(answer, sizeof(answer) + sizeof(tmp) + 1);
Run Code Online (Sandbox Code Playgroud)
strok() 按预期工作。
在这种情况下, realloc() 怎么可能影响 strtok() ?他们甚至不使用相同的变量。期待您的见解。
该realloc函数可以移动先前分配的内存。调用后,返回指向分配内存的指针,传递给它的指针值,如果不同,则不再有效。因此,当您调用时,您strcat(answer, tmp);可能正在写入调用undefined behavior 的已释放内存,在这种情况下,它表现为您看到的奇怪输出。
检查 的返回值后realloc,将该值赋回给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);
Run Code Online (Sandbox Code Playgroud)
还有一个问题:第一次realloc调用内存是完全未初始化的。随后调用strcat它取决于answer包含一个空终止字符串。事实并非如此,这也会调用未定义的行为。
这可以通过malloc-ing 单个字节开始并将其设置为 0来修复,这样您就可以从一个空字符串开始。
char *answer = malloc(1);
if (!answer) return -1;
answer[0] = 0;
Run Code Online (Sandbox Code Playgroud)