简体   繁体   中英

C Programming - Segmentation fault when Manipulating Array of Strings

I am struggling with a segmentation fault that occurs when the dns variable is changed from size 10 to size 32. I believe the declaration of the dns ariable in main is creating an array of 10 strings, and then when increased to 32, an array of 32 strings.

So when executed with dns variable of size 10, I get output of 4 directory names starting with the letter D. This is the expected output.

If I increase dns variable to size 32, I still get the 4 directory names and then immediately afterwards, a Segmentation fault.

It has been a very long time since I have coded and I am sure I am violating memory somewhere.

Any help is greatly appreciated.

Thanks,

Dan.

void ld_dirs(char *strings[])
{
   int count;
   DIR *dp;
   struct dirent *ep;

   dp = opendir ("/tmp/sysinfo/inputs");
   if (dp != NULL)
   {
      count = 0;

      while (ep = readdir (dp))
      {
         if (ep->d_name[0] == 'D')
         {
            strings[count] = malloc (80 * sizeof(char));
            strings[count] = ep->d_name;
            count ++;
         }
      }

      closedir (dp);
   }
   else
      perror ("Could not open the directory");
}

int main ()
{
   char cwd[120];
   int count, count2;
   char *dns[10];
   char *path;
   if (getcwd(cwd, sizeof(cwd)) != NULL)
      printf ("\nCurrent working directory : %s\n\n\n", cwd);
   else
      perror ("getcwd() error");

   ld_dirs (dns);

   count = 0;

   puts ("List of valid inputs :\n");

   while (dns[count] != NULL)
   {
      puts (dns[count]);
      count ++;
   }     

   printf ("There are %d valid inputs\n", count);
   return 0;
}

One problem I see right away is you are continuing to reuse the return value of readdir for different string table entries and overwriting the address you just allocated to hold the name. But I don't think that readdir is ensured to return a new, allocated directory entry structure for each call. I suspect not, and it's only a matter of time before accessing one of the prior ones results in a segmentation fault.

You'll need to copy out the data from each directory entry read with readdir :

  while (ep = readdir (dp))
  {
     if (ep->d_name[0] == 'D')
     {
        strings[count] = malloc(80 * sizeof(char));
        //ERROR: strings[count] = ep->d_name;
        strcpy(strings[count], ep->d_name);  //CORRECTED
        count ++;
     }
  }

I did not check for additional errors beyond this point.

Problems that I see:

  1. Size of array.

    You have declared:

     char *dns[10]; 

    You don't have any code in ld_dirs to make sure that you don't use strings beyond what it can legally hold.

  2. You have not initialized the items in dirs to NULL yet you are counting on the value of the items to be NULL in the following while loop.

     while (dns[count] != NULL) { puts (dns[count]); count ++; } 

You can fix these problems by:

  1. Initialize the items in dns to be NULL .

     char *dns[10] = {0}; 
  2. Pass the size of the array to ld_dir and make sure that you don't use any more than you are legally supposed to.

    Change the function interface to:

     void ld_dirs(char *strings[], int size) 

    Change the call to:

     ld_dirs (dns, sizeof(dns)/sizeof(*dns)); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM