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);