Segmentation fault from fgets ()
I have a list of urls in a text file and I am trying to store them in a structure as host and page. I have a problem with this code. It returns sigsegv . Any ideas?
char buf[100];
.......
while ( fgets ( buf, 100, fin ) != NULL )
{
buf [ strlen (buf) - 1 ] = '\0';
informatii.intrari++;
informatii.urluri[informatii.intrari-1].status=-1;
printf("BUFFER: %s\n", buf);
if( strncmp ("http://",buf,7) == 0 )
memmove (buf, buf+7, strlen (buf));
if( strncmp("https://",buf,8) == 0 )
memmove (buf, buf+8, strlen (buf));
printf("BUFFER: %s\n", buf);
if ( strchr ( buf , '/' ) == NULL)
{
strcpy ( informatii.urluri [ informatii.intrari - 1 ].host, buf);
strcpy ( informatii.urluri [ informatii.intrari - 1 ].page, "/");
}
else
{
memmove ( informatii.urluri [ informatii.intrari - 1 ].page,
buf+(strchr ( buf , '/' )-buf),
strlen(buf) );
}
memset(buf , 0 , 100 );
}
EDIT Structures from OP's comment
struct urlinfo
{
unsigned short status;
char* serror;
char host[100];
char page[100];
};
struct informati
{
int intrari;
int time;
char* email;
struct urlinfo urluri[50];
} informatii;
END EDIT
Edit: After following some of your advice, I was able to get it to work, but there are some things I don't understand. This is the final code.
`struct urlinfo
{
unsigned short status;
char* serror;
char host[100];
char page[100];
};
struct informati
{
int intrari;
int time;
char* email;
struct urlinfo urluri [MAX_URLS];
}informatii;
int configurare(char* fisier)//citim si memoram fisierul de configurare
{
FILE* fin;
char buf[100];
char* temp;
int i;
if((fin = fopen(fisier,"r")) == NULL)//verificam fisierul de intrare
{
printf("Eroare la fisierul de configurare.Se va folosi fisierul default configurare.txt.\n");
fin = fopen("configurare.txt","r");
}
informatii.intrari = 0;
informatii.time = 30;
informatii.email = NULL;`
while ( fgets ( buf, 100, fin ) != NULL )
{
//buf [ strlen (buf) - 1 ] = '\0';
if (informatii.intrari >= 50) {
printf("URLs overflow...!\n");
break;}
informatii.urluri[ informatii.intrari ].status=-1;
informatii.urluri[ informatii.intrari ].serror= NULL;
if( strncmp ("http://",buf,7) == 0 )
memmove (buf, buf+7, strlen (buf) );
if( strncmp("https://",buf,8) == 0 )
memmove (buf, buf+8, strlen (buf) );
temp = strchr ( buf , '/' );
if ( temp == NULL)
{
memcpy ( informatii.urluri [ informatii.intrari ].host, buf,strlen(buf)+1);
strncpy ( informatii.urluri [ informatii.intrari ].page, "/\0",2);
}
else
{
memcpy ( informatii.urluri [ informatii.intrari ].host, buf,strlen(buf)-strlen(temp));
memmove ( informatii.urluri [ informatii.intrari ].page, temp, strlen(temp));
}
informatii.intrari++;
memset(buf , '\0' , 100 );
}
}
fclose(fin);
return 0;
}`
If I use this buf [ strlen (buf) - 1 ] = '\0';
one to remove trayling '\ n', when I use printf somehow, the first character on the line is not printed (eg if I have printf ("Buf% s", buf) it will print "uf" and then the string buf. And if I try to use it if( strncmp ("http://",buf,7) == 0 )
memmove (buf, buf+7, strlen (buf) -7 );
again, I have a wrong return string, some letter from the end of the string will be copied after the '\ n' character in the string.
source to share
Aside from the relevant comment from WhozCraig (buf read outside of its space), I don't see anywhere a way to save a loop to store more than 50 URLs. If more than 50 URLs are read, the urluri array gets overflowed and the heap may get corrupted. This can result in a file descriptor fin (more likely a pointer to it) that changes when a segway is invoked in fgets.
-
Easy to make sure you are reading 50 or less urls, read add as first instruction
while ( fgets ( buf, 100, fin ) != NULL ) { if (informatii.intrari >= 50) { printf("URLs overflow...!\n"); break; }
-
Is it
informatii.intrari
initialized up to0
somewhere before the time? -
By the way, you could have taken the opportunity to name the constant 50
#define MAX_URLS 50
and use
MAX_URLS
instead of 50 in the program. -
Alternatively, you can put
informatii.intrari ++;
at the end of while, using
[informatii.intrari]
instead[informatii.intrari - 1]
in a loop. -
And
buf+(strchr ( buf , '/' )-buf)
there isstrchr ( buf , '/')
, since strchr returns a pointer inside buf. (and since the same strchr is used twice, while buf has not changed at the same time, you should put its return value in a variablechar *pos = strchr(buf, '/');
and use pos instead to avoid calling strchr again.
source to share