segfault in using getline() function in C

Advertisements

I was implementing a basic getline() function for reading content of file and writing it to terminal however

this works completely fine

#include<stdlib.h>
int main(int argc , char *argv[])
{
    FILE *fp = fopen(argv[argc-1],"r");
    if(fp == NULL)
    {
        printf("error : can't open file");
        exit(1);
    }
    char *buf = NULL;
    size_t linelen  = 0;
    size_t linecapp = 0;
    while((linelen = getline(&buf,&linecapp,fp)) !=-1)
    {
        fwrite(buf,linelen,1,stdout);
    }
    fclose(fp);
    return 0;
}

but this

#include<stdio.h>
#include<stdlib.h>
int main(int argc , char *argv[])
{
    FILE *fp = fopen(argv[argc-1],"r");
    if(fp == NULL)
    {
        printf("error : can't open file");
        exit(1);
    }
    char *buf = NULL;
    size_t linelen  = 0;
    size_t linecapp = 0;
    while((linelen = getline(&buf,&linecapp,fp)) >= 0)
    {
        fwrite(buf,linelen,1,stdout);
    }
    fclose(fp);
    return 0;
}

is giving segmentation fault.
only thing that differ is
!= -1 and >= 0 in while loop which is the same thing.

What I tried
printf("%zu\n", linelen);
inside my while loop and I got this
<\n><\n>

116
hello world this is a test file to bes used for the purpose of learning basics of unix sys calls and c programming 
77
this is just an extra line to elongate the file followed by more extra lines
55
for example this is a line used in elongating the file
22
this is another line 
141
this line contain special characters like œ∑´®†¥¨ˆøπåß∂ƒ©˙∆˚¬¬¬…≈ç√∫˜µ≤≥÷¡™£¢∞§¶•ªº–
52
this line contain some numbers 1 2 3 5 7 4 6 8 9 10
18446744073709551615
his line contain some numbers 1 2 3 5 7 4 6 8 9 10
?¥¨ˆøπåß∂ƒ©˙∆˚¬¬¬…≈ç√∫˜µ≤≥÷¡™£¢∞§¶•ªº–
Xjm??ͫ?????@|m? ?5?r?@?@:?#??Zm@?` `@?`?`?Zm???#? ??#????#?????#?@?`X???\/var/folders/l5/h45_tftn3w18ws8vshrpxlsr0000gn/T//private/tmp/com.apple.launchd.pIOsn5DWl2/Listeners0?``SSH_AUTH_SOCK??`??????????????????`??`P ?b??,?,?8Zm@??Xm? ??`(?`?`HOME?Xm?D<?B`38?`P`PATH?Xm?81??` ?`?`TMPDIR?Xm?83?`??!???c?8???W&???ǀ?G???w+???C???????`??`@``?```?Z??`ԥ`???`???`???`?@`?a??\_?x?`?`?`?Z????^??\_?x?`????`?pm??   ??
m ??um??     ?x ?h
m?
 ?@
m?? ??
m?`
 ??
zsh: segmentation fault  ./getlinefunc ../../sampletextfile.txt

for comparison here’s orignal sampletextfile

hello world this is a test file to be used for the purpose of learning basics of unix sys calls and c programming 
this is just an extra line to elongate the file followed by more extra lines
for example this is a line used in elongating the file
this is another line 
this line contain special characters like œ∑´®†¥¨ˆøπåß∂ƒ©˙∆˚¬¬¬…≈ç√∫˜µ≤≥÷¡™£¢∞§¶•ªº–
this line contain some numbers 1 2 3 5 7 4 6 8 9 10

it’s taking on some very large value for linelen at the end.

>Solution :

The variable linelen is unsigned, and so it is always greater or equal to zero.

The documentation states:

On error, returns -1 and sets feof or ferror on stream.

The equality test with -1 works because the negative return value is automatically converted to its unsigned equivalent when assigned to an unsigned value, then the -1 is automatically converted to unsigned when compared to an unsigned value.

The actual issue here is that return type of getline is ssize_t which is the signed version of a size_t value. So you should be using the appropriate type instead, then both versions of your loop will work:

char *buf = NULL;
ssize_t linelen  = 0;
size_t linecapp = 0;
while((linelen = getline(&buf,&linecapp,fp)) >= 0)
{
    fwrite(buf,linelen,1,stdout);
}
free(buf);

Leave a ReplyCancel reply