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。
我有以下用 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。