简体   繁体   中英

C programming - Strdup not capturing and storing filenames in array correctly

I'm trying to store file names in an array. The array is in a struct, and I want to store the names of files found in a directory in the array. However, the process that I'm using to store the names seems to be corrupting 2 or 3 of the names during the process. I think the problem is with the strdup keyword. Whenever I run my program either it reads in the program executable (which is in the directory above the directory I'm reading the files from), or weird symbols stored in the first few array locations. The following is part of my program where I'm trying to capture and store the file names, and a picture of the output results:

typedef struct{
  char *filename;
}filename;

typedef struct Configs{
  char file_data_path[50];
  char event_log_path[50];
  filename *fn_data;
}Configs;

typedef struct TestConfigs{
  bool done;
  int selection;
  int attempts_counter;
  Configs tConfig;
}TestConfigs;

void read_files(struct TestConfigs *setup);

int main(void) {
  printf("Hello Test\n");
  TestConfigs setup;
  read_files(&setup);
  system("pause");
  return EXIT_SUCCESS;
}

void read_files(struct TestConfigs *setup)
{
  setup->done = false;
  setup->attempts_counter = 3;

  char cwd[1024];
  DIR *dir = NULL;
  struct dirent *pent = NULL;
  struct stat info;
  int total_num_of_files = 0;

  strcpy(setup->tConfig.file_data_path, "data/");

  chdir(setup->tConfig.frame_data_path);
  if((getcwd(cwd, sizeof(cwd))) != NULL)
  {
      printf("Current Directory: %s\n", cwd);
  }

  dir = opendir(cwd);

  if(dir != NULL)
  {
     while((pent = readdir(dir)) != NULL)
     {
         if(stat(pent->d_name, &info))
         {
             printf("ERROR: stat%s: %s\n", pent->d_name, strerror(errno));
         }
         else
         {
             if(S_ISREG(info.st_mode))
             {
                 if((strcmp(pent->d_name, ".cproject") == 0) || (strcmp(pent->d_name, ".project") == 0))
                 {
                     continue;
                 }
                 else
                 {
                     total_num_of_files++;
                 }
             }
         }
     }
     printf("# of files found: %d\n", total_num_of_files);
     rewinddir(dir);

     // SETUP ARRAY HERE!
     setup->tConfig.fn_data = malloc(total_num_of_files);
     total_num_of_files= 0;

     printf("During Storage Process:\n");
     while((pent = readdir(dir)) != NULL)
     {
         if(stat(pent->d_name, &info))
         {
             printf("ERROR: stat%s: %s\n", pent->d_name, strerror(errno));
         }
         else
         {
             if(S_ISREG(info.st_mode))
             {
                 if((strcmp(pent->d_name, ".cproject") == 0) || (strcmp(pent->d_name, ".project") == 0))
                 {
                     continue;
                 }
                 else
                 {
                     setup->tConfig.fn_data[total_num_of_files].filename = (char*)malloc(sizeof(pent->d_name));
                     setup->tConfig.fn_data[total_num_of_files].filename = strdup(pent->d_name);  // <- Possible source of the storage problem
                     printf("Filename stored in fn_data[%d] = %s\n", total_num_of_files, setup->Config.fn_data[total_num_of_files].filename);
                     total_num_of_files++;
                 }
             }
         }
     }

     printf("\n");
     printf("After Storage Process:\n");
     for(int i = 0; i < total_num_of_files; i++)
     {
         printf("Filename stored in fn_data[%d] = %s\n", i, setup->tConfig.fn_data[i].filename);
     }
  }
  closedir(dir);
}

Output results here

What can I do to resolve the corrupt storage of the filenames in the first few array locations? How come only the first few locations aren't properly storing the filenames, but the other locations are Ok? Is the issue with strdup , and if so, what's a good alternative for capturing and storing the file names in the array? Thanks in advance!

This:

setup->tConfig.fn_data[total_num_of_files].filename = (char*)malloc(sizeof(pent->d_name));
setup->tConfig.fn_data[total_num_of_files].filename = strdup(pent->d_name);  // <- Possible source of the storage problem

makes no sense; the strdup() will overwrite the pointer returned by malloc() and that memory will be forever lost ("leaked") which is bad.

You don't have to allocate memory for strdup() , it does that for you. It's basically:

char * strdup(const char *s)
{
  const size_t sz = strlen(s) + 1;
  char * const p = malloc(sz);
  if (p != NULL)
    memcpy(p, s, sz);
  return p;
}

setup->tConfig.fn_data = malloc(total_num_of_files);

One byte per file?

Need, eg, setup->tConfig.fn_data = malloc(total_num_of_files * sizeof(filename));

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