MEU*_*ULT 0 c memory-management getline realloc segmentation-fault
我正在尝试制作一个简单版本的getline.它应该从stdin读取一行,根据需要重新分配缓冲区的大小.它还应该返回读取的字符数.它需要一个char**,以便以后可以释放重新分配的缓冲区.为什么我会遇到段错误?
继承人我的版本:
int get_input_line(char **buff, int start_size) {
char c;
int stop = 0, length = 0, k = start_size;
while(!stop) {
if(length > k) {
k += 50;
buff = (char *)(realloc(buff, start_size + 1));
}
c = getchar();
if(c == '\n'){
stop = 1;
}
buff[length] = c;
length++;
}
return length;
}
Run Code Online (Sandbox Code Playgroud)
这是电话:
char *buff = (char *)(malloc(50 + 1));
get_input_line(&buff, 50);
printf("%s", buff);
Run Code Online (Sandbox Code Playgroud)
你可能意味着:
*buff = (realloc(*buff, new_size));
^ ^
Run Code Online (Sandbox Code Playgroud)
和
(*buff)[length] = c;
Run Code Online (Sandbox Code Playgroud)
你也错过了0终结者.
作为nos指出,length > k应该是length >= k.
你没有可靠地检测EOF.您需要保存的结果getchar()在int和不char.而且你不应该试图存储EOF在缓冲区中.
你没有检查你的内存分配.
你不是null终止输出字符串,所以printf()in main()可能会崩溃.
通过分配51个字节并告诉函数它只有50个字节可以用来混淆某人(也许是我,也许是编译器,也许是你自己).
而且,最重要的是,您需要*buff在函数内部的大多数点使用,特别是在添加字符时:
(*buff)[length++] = c;
Run Code Online (Sandbox Code Playgroud)
你真的应该更加关注所有这些编译器警告.如果你的编译器没有给你任何东西,那就得到一个更好的编译器(或者打开警告标志 - 但你应该被编译器在其默认模式下尖叫).
此外,你有realloc()三个理由误导.一个是*buff问题.第二个是你想要的尺寸,而k不是start_size + 1.另一个是您将结果分配给输入参数.这是一个'禁忌',因为如果分配失败,你就失去了指向先前(仍然)分配数据的指针.总是使用成语:
void *new_data = realloc(old_data, new_size);
if (new_data == 0)
...deal with out of memory error...
else
{
old_data = new_data;
old_size = new_size;
}
Run Code Online (Sandbox Code Playgroud)
应用于您的代码,这意味着:
char *new_buff = (char *)realloc(*buff, k); // NOT start_size+1!!!
if (new_buff == 0)
...deal with out of memory error...
else
*buff = new_buff;
Run Code Online (Sandbox Code Playgroud)
有人反对演员malloc()和realloc()和calloc(); 有些人更喜欢演员阵容.双方都有不同程度的论点.我更喜欢演员 - 我尊重那些不喜欢演员的人.我们出于不同的原因得出了不同的结论.
我还没有研究其他'off-by-one'错误的代码.我怀疑也可能有几个.