2012-05-11 9 views
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が実行されません。return 0は実行できません。他のいくつかの行によってスタックオーバーフローが発生する可能性はありますか?任意のアイデアをいただければ幸いです。

+0

保存している文字列にスペースを割り当てたことはありません。いくつかの場所でmalloc(0)を呼び出しますが、0バイトのスペースを割り当てることはあなたにとって非常に有用ではありません。 –

+3

文字列のメモリを(char *)ポインタで管理するのではなく、std :: string(または他の文字列クラス)を使用すると、Btwの生活がはるかに楽になります。 –

答えて

3

コンストラクタでは、宛先char*を割り当てずにchar配列を保存しています。あなたは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; 

}; 

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

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

ます。またstd::stringの使用を検討、またはでなければなりません有効なバイト数を割り当てるために、少なくともそれを修正してください。

+0

ありがとう非常に私は今あなたが提案した変更を行ったsegフォールトの問題が出ています:) – merveotesi

+0

と参照/アドレスstd :: stringで渡すことはできますか? – merveotesi

+0

喜んで助けました。はい、ポインタ/参照を使用してそれらを渡すことができます。 – mfontanini

1

gdbを使用しているので、私はvalgrindが利用可能であると仮定します。あなたのmemcpyの使用は安全ではなく、valgrindはあなたのプログラムが持つと思われる様々なメモリ破損の問題を見つけるのを助けるべきです。 Jeremy Friesnerとfontaniniの両方が示唆しているように、naked char *の代わりにstd :: stringを使用します。

+0

ありがとう非常に私はstd:stringですべてのchar *を変更し、今は期待どおりに動作しています。 – merveotesi