我是否需要为Dirent结构分配内存 [英] Do I need to Allocate Memory for a Dirent Structure

查看:94
本文介绍了我是否需要为Dirent结构分配内存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  • 平台:Windows XP Service Pack 3
  • 编译器:代码:: Blocks版本12.11

我目前正在编写一个程序,该程序将使用POSIX目录功能递归删除给定目录.但是我在readdir()及其对应的dirent结构上遇到了问题.我在readdir的文档中读到,对该函数的多次调用将覆盖数据保留在函数返回的结构中.因此,我认为readdir()必须为结构本身分配内存,然后将指针地址重新分配给捕获其返回值的结构.我测试了这个理论,我为它的成员d_name分配了正确的readdir()内存.我遇到的问题是,当目录流为空时,readdir返回NULL指针,因此我使用带有条件(dirent_ptr!= NULL)的while循环来迭代整个目录.但是因为readdir()将处理结构的内存分配,所以我只声明一个dirent结构,然后让readdir()来完成它的工作.出于某种原因,将unrent结构初始化为NULL(或者可能是我的编译器),所以我的循环永远不会启动,因为它的条件语句最初不是真的.所以我想我的问题是我在这里做错了什么?

I am currently writing a program that will recursively delete a given directory using the POSIX directory functions. But I am having a problem with readdir() and its counterpart the dirent structure. I read in readdir's documentation that multiple calls to the function will overwrite the data held in the structure returned by the function. 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. I tested this theory and I was correct readdir() allocated memmory for it's member d_name. 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. But because readdir() will handle the memmory allocation of the structure I simply declare a dirent structure and let readdir() do its job. 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. 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;

不是解析相对路径,而是简单地将cd转换为作为参数给出的路径,然后使用.和..通配符移动到目录,以便相对路径(d_names)是有效的.开关结构也只包含命令行开关,应该忽略,我知道以下代码中的错误,但由于无法克服上述问题,我无法修复它们.

Rather than resolving relative paths I simply cd to the path given as an argument and then I use the . and .. wildcards to move threw the directorys so that relative paths(d_names) are valid. 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;
}

推荐答案

您的代码结构应类似于以下内容(为清楚起见,省略了大多数错误检查):

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;
}

这篇关于我是否需要为Dirent结构分配内存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆