在我自己的getline版本上出现故障

时间:2012-01-15 21:51:57

标签: c memory-management segmentation-fault getline realloc

我正在尝试制作一个简单的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);

3 个答案:

答案 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'