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

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)

cni*_*tar 6

你可能意味着:

*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.

  • 并且`length> k`应该是`length> = k` (3认同)

Jon*_*ler 5

你没有可靠地检测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'错误的代码.我怀疑也可能有几个.