我正在尝试制作一个简单的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;
}
这就是电话:
char *buff = (char *)(malloc(50 + 1));
get_input_line(&buff, 50);
printf("%s", buff);
答案 0 :(得分:6)
你可能意味着:
*buff = (realloc(*buff, new_size));
^ ^
和
(*buff)[length] = c;
你也错过了0终结者。
正如nos
指出的那样,length > k
应为length >= k
。
答案 1 :(得分:5)
您没有可靠地检测到EOF。您需要将getchar()
的结果保存在int
而不是char
中。并且您不应该尝试将EOF
存储在缓冲区中。
您没有检查内存分配。
您不是null终止输出字符串,因此printf()
中的main()
可能会崩溃。
通过分配51个字节并告诉函数它只有50个字节可供使用,你会混淆某人(也许是我,也许是编译器,也许是你自己)。
最重要的是,你需要在函数中的大多数点使用*buff
,特别是在添加字符时:
(*buff)[length++] = c;
你真的应该更加关注所有这些编译器警告。如果你的编译器没有给你任何东西,那就得到一个更好的编译器(或打开警告标志 - 但你应该在编译器的默认模式下尖叫)。
另外,你有三个理由误导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;
}
应用于您的代码,即:
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;
有些人反对malloc()
和realloc()
以及calloc()
上的演员;有些人更喜欢演员阵容。双方都有不同程度的论点。我更喜欢演员 - 我尊重那些不喜欢演员的人。我们出于不同的原因得出了不同的结论。
我还没有研究过其他“off-by-one”错误的代码。我怀疑其中也可能有几个。
答案 2 :(得分:4)
该行
buff = (char *)(realloc(buff, start_size + 1));
应该是
*buff = (char *)(realloc(*buff, k + 1));
另外
buf[length] = c
应该是
*buf[length] = c
此外,我认为您忘记存储最终'\0'
。