0
#include <stdio.h>
#include <dirent.h> 
#include <sys/types.h> 
#include <sys/param.h> 
#include <sys/stat.h> 
#include <unistd.h> 
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <vector>

using namespace std;

enum ElementType { SIMPLEFILE, DIRECTORY, SYMBOLICLINK };

class Element{
public:
    Element(){};

    Element(char *name_, char *full_path_name_, ElementType element_type_, long element_size_)
      : name(NULL), full_path_name(NULL), element_size(0)
    {
        memcpy (name,name_,strlen(name_)+1);
        memcpy (full_path_name,full_path_name_,strlen(full_path_name_)+1);
        element_type=element_type_;
        element_size=element_size_;
    };

    char *name;
    char *full_path_name;
    ElementType element_type;
    long element_size;
};

int inspect(const char *input_path, std::vector<Element>& result_element_array, long *dir_size,const char *full_path ) {
    std::vector<Element> result_element_array_temp;
    DIR           *d;
    struct dirent *dir;
    struct stat buf;
    char *mynamebuf=(char *)malloc(0);
    int c=0;
    size_t base_len = strlen(full_path);

    long dir_size_temp=0;
    char *full_path_temp=(char *)malloc(0);
    char *full_path_dummy=(char *)malloc(0);

    result_element_array_temp.reserve(1000);

    d = opendir( full_path);

    if( d == NULL ) {
        return 1;
    }
    while( ( dir = readdir( d ) )) {
        if( strcmp( dir->d_name, "." ) == 0 || strcmp( dir->d_name, ".." ) == 0 ) {
            continue;
        }

        memcpy (mynamebuf,full_path,strlen(full_path)+1);
        strcat(mynamebuf,(full_path[base_len - 1] == '/' ? "" : "/"));
        strcat(mynamebuf,dir->d_name);
        if (stat(mynamebuf, &buf) != 0) {
            perror(mynamebuf);
            continue;
        }

        if( S_ISDIR(buf.st_mode) ) {//if dir
            chdir( dir->d_name );
            memcpy (full_path_temp,full_path,strlen(full_path)+1);
            strcat(full_path_temp,"/");
            strcat(full_path_temp,dir->d_name);
            (dir_size_temp)=0;

            inspect( ".", result_element_array_temp, &dir_size_temp, full_path_temp  );

            chdir( ".." );
            memcpy (full_path_dummy,full_path_temp,strlen(full_path_temp)+1);
            strcat(full_path_dummy,"/");
            strcat(full_path_dummy,dir->d_name);
            Element element;
            element.name=dir->d_name;
            element.full_path_name=full_path_dummy;
            element.element_type=DIRECTORY;
            element.element_size=dir_size_temp;
            result_element_array.push_back(element);
            result_element_array.insert( result_element_array.end(), result_element_array_temp.begin(), result_element_array_temp.end() );
            (*dir_size)+=(dir_size_temp);
        } else if( S_ISREG(buf.st_mode)) {//if file
            memcpy (full_path_dummy,full_path,strlen(full_path)+1);
            strcat(full_path_dummy,"/");
            strcat(full_path_dummy,dir->d_name);
            Element element;
            element.name=dir->d_name;
            element.full_path_name=full_path_dummy;
            element.element_type=SIMPLEFILE;
            element.element_size=buf.st_size;
            result_element_array.push_back(element);
            (*dir_size)+=buf.st_size;
        } else if( S_ISLNK(buf.st_mode) ) {//if link
            memcpy (full_path_dummy,full_path,strlen(full_path)+1);
            strcat(full_path_dummy,"/");
            strcat(full_path_dummy,dir->d_name);

            Element element;
            element.name=dir->d_name;
            element.full_path_name=full_path_dummy;
            element.element_type=SIMPLEFILE;
            element.element_size=buf.st_size;
            result_element_array.push_back(element);
        } else {
            continue;
        }
    }
    closedir(d);
    return 0;
}

int main(){
    std::vector<Element> result_element_array;
    result_element_array.reserve(3000); 
    long dir_size;
    const char *full_path="/";
    inspect("/", result_element_array, &dir_size,full_path  );

    std::vector <Element>::iterator It;

    for(It = result_element_array.begin(); It != result_element_array.end(); ++It){
        printf("%s\n",(*It).full_path_name);
    }
    return 0;
}

コードは上にあります。ディレクトリエクスプローラーを再帰的に作成することを目指しています。

コードをGDBしたところ、メソッドが再帰的に呼び出されreturn 0たときに到達しましたが、実行できません。他の回線によって引き起こされたスタックオーバーフローに関するものでしょうか?任意のアイデアをいただければ幸いです。inspectreturn 0

4

2 に答える 2

3

コンストラクターでは、宛先を割り当てずに配列をElementmemcpyします。使用を検討する必要があります:charchar*std::string

class Element{
public:
    Element(){};
  Element(char *name_,
  char *full_path_name_,
  ElementType element_type_,
  long element_size_)
      :name(name),
      full_path_name(full_path_name_),
      element_size(0)
  {
      element_type=element_type_;
      element_size=element_size_;
  };
  std::string name;
  std::string full_path_name;
  ElementType element_type;
  long element_size;

};

また、0バイトを実行していて、mallocこのポインターを有効であるかのように使用します。

char *mynamebuf=(char *)malloc(0);

また、有効なバイト数を割り当てるために、の使用を検討するstd::stringか、少なくとも修正する必要があります。

于 2012-05-11T16:17:09.043 に答える
1

gdbを使用しているので、valgrindが使用可能であると想定します。memcpyの使用は安全ではなく、valgrindは、プログラムにあると思われるさまざまなメモリ破損の問題を見つけるのに役立つはずです。Jeremy Friesnerとfontaniniの両方が提案したように、nakedchar*の代わりにstd::stringを使用します。

于 2012-05-11T16:19:15.893 に答える