简体   繁体   English

我是否需要为Dirent结构分配内存

[英]Do I need to Allocate Memory for a Dirent Structure

  • Platform: Windows XP Service Pack 3 平台:Windows XP Service Pack 3
  • Compiler: Code::Blocks version 12.11 编译器:Code :: Blocks版本12.11

I am currently writing a program that will recursively delete a given directory using the POSIX directory functions. 我目前正在编写一个程序,它将使用POSIX目录函数递归删除给定目录。 But I am having a problem with readdir() and its counterpart the dirent structure. 但是我遇到了readdir()及其对应的dirent结构的问题。 I read in readdir's documentation that multiple calls to the function will overwrite the data held in the structure returned by the function. 我在readdir的文档中读到,对函数的多次调用将覆盖函数返回的结构中保存的数据。 So I thought readdir() must allcoate memmory for the struct itself and then simply reassign the pointer address to the structure that captures it's return value. 所以我认为readdir()必须为结构本身创建memmory,然后简单地将指针地址重新分配给捕获它的返回值的结构。 I tested this theory and I was correct readdir() allocated memmory for it's member d_name. 我测试了这个理论,我是正确的readdir()为它的成员d_name分配了memmory。 The problem I am having is that readdir returns a NULL pointer when the directory stream is empty, so I use a while loop with the condition (dirent_ptr != NULL) to iterate the entire directory. 我遇到的问题是当目录流为空时readdir返回一个NULL指针,所以我使用带有条件(dirent_ptr!= NULL)的while循环来迭代整个目录。 But because readdir() will handle the memmory allocation of the structure I simply declare a dirent structure and let readdir() do its job. 但是因为readdir()将处理结构的memmory分配,所以我只是声明一个dirent结构,让readdir()完成它的工作。 Unfourtatnly for some reason dirent structures are initialized to NULL(or it might be my complier) so my loop never starts because it's conditional statement is not initialy true. 由于某种原因unforrtatnly dirent结构初始化为NULL(或者它可能是我的编译器)所以我的循环永远不会启动,因为它的条件语句不是initialy true。 So I guess my question is what am I doing wrong here? 所以我想我的问题是我在这里做错了什么?

Here are important variable declarations and the included librarys. 这是重要的变量声明和包含的库。 Please note that all of these variables are declared globaly. 请注意,所有这些变量都是全局声明的。

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>
#include <string.h>

int recursive_delete(const char *path);
int file_delete(const char *path, int file_size);

struct dirent *direntp;
struct stat *statp;

struct switches
{
    int verbose;
    int no_prompt;
    int continue_if_error;
    int files_only;
}; struct switches switches;

Rather than resolving relative paths I simply cd to the path given as an argument and then I use the . 我只是cd到作为参数给出的路径,而不是解析相对路径,然后我使用。 and .. wildcards to move threw the directorys so that relative paths(d_names) are valid. 和..移动的通配符抛出directorys,使相对路径(d_names)有效。 Also the switches structure simply contains command line switches and should be ignored and I am aware of errors in the following code but unfourtantly I cannot fix them because I cannot get past the above mentioned problem. 此外,开关结构只包含命令行开关,应该被忽略,我知道以下代码中的错误,但是我无法解决它们,因为我无法解决上述问题。

int recursive_delete(const char *path)
{
    DIR *dirp;
    int return_value = 0;
    int recursive_return_value = 0;

    if((chdir(path)) == -1)
    {
        perror("ERROR(3)");
        return 1;
    }
    printf("CDED to \"%s\"\n", path);

    dirp = opendir(".");
    if(dirp == NULL)
    {
        perror("ERROR(4)");
        return 1;
    }
    printf("OPENED \"%s\"\n", path);

    while(direntp != NULL)
    {
        direntp = readdir(dirp);
        if( (direntp == NULL) && (errno != 0) )
        {
            perror("ERROR(5)");
            return 1;
        }
        printf("READ \"%s\" FROM \"%s\"\n", direntp->d_name, path);

        if( (strcmp(direntp->d_name, ".")!=0) && (strcmp(direntp->d_name, "..")!=0) )
        {
            if((stat(direntp->d_name, statp)) == -1)
            {
                perror("ERROR(6)");
                return 1;
            }
            printf("STATED \"%s\"\n", direntp->d_name);

            if(S_ISREG(statp->st_mode))
            {
                printf("DELETING \"...\\%s\\%s\"\n", path, direntp->d_name);
                return_value += file_delete(direntp->d_name, statp->st_size);
                if( (!switches.continue_if_error) && (return_value != 0) )
                {
                    break;
                }
            }
            else if(S_ISDIR(statp->st_mode))
            {
                printf("\n\n\nCALLING RECURSIVE DELETE with \"%s\"\n", direntp->d_name);
                recursive_return_value = recursive_delete(direntp->d_name);
                return_value += recursive_return_value;

                if( (!switches.continue_if_error) && (recursive_return_value != 0) )
                {
                    break;
                }

                if( (!switches.files_only) && (recursive_return_value == 0) )
                {
                    if((chdir("..")) == -1)
                    {
                        perror("ERROR(6)");
                        return 1;
                    }
                    printf("CDED BACK TO \"%s\" FROM \"%s\"\n", path, direntp->d_name);

                    if((rmdir(direntp->d_name)) == -1)
                    {
                        perror("ERROR(7)");
                        return 1;
                    }

                    if(switches.verbose)
                    {
                        printf("DELETED DIRECTORY \"...\\%s\\\"\n\n\n", direntp->d_name);
                    }
                }
            }
        }
    }

    return return_value;
}

From the code attached, it's not clear where direntp is being initialized (before the while loop). 从附加的代码中,不清楚direntp的初始化位置(在while循环之前)。 Possibly try something like: 可能尝试类似的东西:

direntp = readdir(dirp);
while(direntp != NULL)
{
    // all your work here

    direntp = readdir(dirp);
}

This pattern ensures that direntp is initialized and updated for your while loop. 此模式确保为您的while循环初始化和更新direntp However, on second glance of your code I'm not exactly sure what the while loop is supposed to be doing in the first place. 但是,在你的代码的第二眼看来,我并不完全确定while循环应该首先做什么。 How is direntp or dirp changing in your loop? direntpdirp如何在循环中改变?

It's possible that you can just get away with an if test (instead of the while ) and just let the recursive call handle the "looping" effect... 你可以通过if测试(而不是while )来逃避,只需让递归调用处理“循环”效果......

Your code structure should look something like thhis (with most error checks omitted for clarity): 您的代码结构应该类似于此(为清晰起见,省略了大多数错误检查):

int recursive_delete(const char *path)
{
  DIR* dirp = NULL;
  int return_value = 0;
  char* initial_cur_dir = malloc(1000);

  getcwd(initial_cur_dir, 1000);
  chdir(path);
  dirp = opendir(".");

  while (dirp != NULL)
  {
    struct dirent* direntp;
    struct stat stat;

    direntp = readdir(dirp);

    if (direntp == NULL)
      break;

    stat(direntp->d_name, &stat);

    if (S_ISDIR(statp->st_mode))
    {
      if (strcmp(direntp->d_name, ".") && strcmp(direntp->d_name, ".."))
      {
        return_value += recursive_delete(direntp->d_name);
      }
    }
    else if (S_ISREG(statp->st_mode))
    {
      unlink(direntp->d_name);
    }
  }

  if (initial_cur_dir != NULL)
  {
    chdir(initial_cur_dir);
    rmdir(path);
  }

ErrorLabel: // you should goto here when an error is detected

  if (dirp != NULL)
  {
    closedir(dirp);
  }

  if (initial_cur_dir != NULL)
  {
    chdir(initial_cur_dir);
    free(initial_cur_dir);
  }

  return return_value;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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