簡體   English   中英

我是否需要為Dirent結構分配內存

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

  • 平台:Windows XP Service Pack 3
  • 編譯器:Code :: Blocks版本12.11

我目前正在編寫一個程序,它將使用POSIX目錄函數遞歸刪除給定目錄。 但是我遇到了readdir()及其對應的dirent結構的問題。 我在readdir的文檔中讀到,對函數的多次調用將覆蓋函數返回的結構中保存的數據。 所以我認為readdir()必須為結構本身創建memmory,然后簡單地將指針地址重新分配給捕獲它的返回值的結構。 我測試了這個理論,我是正確的readdir()為它的成員d_name分配了memmory。 我遇到的問題是當目錄流為空時readdir返回一個NULL指針,所以我使用帶有條件(dirent_ptr!= NULL)的while循環來迭代整個目錄。 但是因為readdir()將處理結構的memmory分配,所以我只是聲明一個dirent結構,讓readdir()完成它的工作。 由於某種原因unforrtatnly dirent結構初始化為NULL(或者它可能是我的編譯器)所以我的循環永遠不會啟動,因為它的條件語句不是initialy true。 所以我想我的問題是我在這里做錯了什么?

這是重要的變量聲明和包含的庫。 請注意,所有這些變量都是全局聲明的。

#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到作為參數給出的路徑,而不是解析相對路徑,然后我使用。 和..移動的通配符拋出directorys,使相對路徑(d_names)有效。 此外,開關結構只包含命令行開關,應該被忽略,我知道以下代碼中的錯誤,但是我無法解決它們,因為我無法解決上述問題。

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

從附加的代碼中,不清楚direntp的初始化位置(在while循環之前)。 可能嘗試類似的東西:

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

    direntp = readdir(dirp);
}

此模式確保為您的while循環初始化和更新direntp 但是,在你的代碼的第二眼看來,我並不完全確定while循環應該首先做什么。 direntpdirp如何在循環中改變?

你可以通過if測試(而不是while )來逃避,只需讓遞歸調用處理“循環”效果......

您的代碼結構應該類似於此(為清晰起見,省略了大多數錯誤檢查):

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