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.

+3


source to share


1 answer


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 to 0

    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 is strchr ( 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 variable char *pos = strchr(buf, '/');

    and use pos instead to avoid calling strchr again.

0


source







All Articles