无法在非常特殊的情况下重新分配内存
Can not reallocate memory in a very peculiar circumstance
几乎最小的可重现示例:
prog.c
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char *buffer;
int c;
size_t bufsiz = 1024, i = 0;
if (!(buffer = malloc(bufsiz))) {
fputs("malloc() failed!\n", stderr);
return 1;
}
while (EOF != (c = fgetc(stdin))) {
buffer[i] = c;
if (++i == bufsiz && !(buffer = realloc(buffer, bufsiz *= 2))) {
fputs("realloc() failed! (loop)\n", stderr);
return 1;
}
}
buffer[i] = '[=10=]';
if (!(buffer = realloc(buffer, i))) {
fputs("realloc() failed! ", stderr);
fprintf(stderr, "%d\n", i);
return 1;
}
fputs(buffer, stdout);
return 0;
}
我用这个命令编译和 运行:
gcc prog.c -o prog
此命令按预期将 prog.c
的内容复制到 exp
:
cat prog.c | ./prog > exp
此命令打印错误消息“realloc() 失败! 0”:
cat prog.c | ./prog > prog.c
我还没有找出这种奇怪行为背后的原因...
P.S.: 我正在使用 GNU cat 和 bash
恭喜,您(重新)发现了系统实现 realloc
中的一个错误,其中将“成功”大小调整为 0 与错误没有区别。按照规定,如果 realloc
returns 一个空指针,它已经失败并且旧对象仍然存在。但一些历史实现将 realloc(p,0)
视为 free(p)
。 C 标准的未来版本允许这种行为,并反对使用零大小的 realloc
,所以如果你想像这样使用 realloc
,你应该确保你没有传递零大小.
正如 Eric Postpischil 在评论中指出的那样:
Where does your program put a null character at the end of the string in the buffer?
您的缓冲区的可能大小为 0 的事实表明存在问题 - 您忘记保留 space 来终止字符串 - 如果您修复此问题,即使是 zero-length 字符串采用非零字节数。
在 cat prog.c | ./prog > prog.c
中,shell 解析命令,发现有一个重定向到 prog.c
,并打开 prog.c
进行写入,这将删除之前的任何内容文件。然后 cat prog.c
看到一个空文件并将其复制到标准输出。 ./prog
忠实地再现了这个空流。
几乎最小的可重现示例:
prog.c
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char *buffer;
int c;
size_t bufsiz = 1024, i = 0;
if (!(buffer = malloc(bufsiz))) {
fputs("malloc() failed!\n", stderr);
return 1;
}
while (EOF != (c = fgetc(stdin))) {
buffer[i] = c;
if (++i == bufsiz && !(buffer = realloc(buffer, bufsiz *= 2))) {
fputs("realloc() failed! (loop)\n", stderr);
return 1;
}
}
buffer[i] = '[=10=]';
if (!(buffer = realloc(buffer, i))) {
fputs("realloc() failed! ", stderr);
fprintf(stderr, "%d\n", i);
return 1;
}
fputs(buffer, stdout);
return 0;
}
我用这个命令编译和 运行:
gcc prog.c -o prog
此命令按预期将 prog.c
的内容复制到 exp
:
cat prog.c | ./prog > exp
此命令打印错误消息“realloc() 失败! 0”:
cat prog.c | ./prog > prog.c
我还没有找出这种奇怪行为背后的原因...
P.S.: 我正在使用 GNU cat 和 bash
恭喜,您(重新)发现了系统实现 realloc
中的一个错误,其中将“成功”大小调整为 0 与错误没有区别。按照规定,如果 realloc
returns 一个空指针,它已经失败并且旧对象仍然存在。但一些历史实现将 realloc(p,0)
视为 free(p)
。 C 标准的未来版本允许这种行为,并反对使用零大小的 realloc
,所以如果你想像这样使用 realloc
,你应该确保你没有传递零大小.
正如 Eric Postpischil 在评论中指出的那样:
Where does your program put a null character at the end of the string in the buffer?
您的缓冲区的可能大小为 0 的事实表明存在问题 - 您忘记保留 space 来终止字符串 - 如果您修复此问题,即使是 zero-length 字符串采用非零字节数。
在 cat prog.c | ./prog > prog.c
中,shell 解析命令,发现有一个重定向到 prog.c
,并打开 prog.c
进行写入,这将删除之前的任何内容文件。然后 cat prog.c
看到一个空文件并将其复制到标准输出。 ./prog
忠实地再现了这个空流。