2012-05-11 89 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 0inspect方法遞歸調用,但return 0無法執行。可能是由於某些其他行引起的stackoverflow?任何想法將不勝感激。

+0

它似乎沒有爲您要存儲的字符串分配任何空間。你可以在幾個地方調用malloc(0),但爲0字節分配空間不會對你有用。 –

+3

如果你使用std :: string(或者其他一些字符串類),而不是試圖通過(char *)指針自己管理字符串內存,那麼對你而言,生活就會容易得多。 –

回答

3

在您的Element構造函數中,您將memcpy-ing 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; 

}; 

您還執行0 malloc一個字節,然後使用該指針,如果它是有效的:

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

你也應該考慮使用std::string,或在至少修復它以分配有效的字節數量。

+0

非常感謝我做了你現在提出的改變seg故障問題是過時:) – merveotesi

+0

和我可以通過引用/地址與std ::字符串? – merveotesi

+0

很高興幫助。是的,你可以使用指針/引用來傳遞它們。 – mfontanini

1

由於您使用的是gdb,我將假定valgrind可用。你對memcpy的使用是不安全的,valgrind應該幫助你找出程序似乎存在的各種內存損壞問題。像Jeremy Friesner和fontanini都建議,使用std :: string而不是naked char *。

+0

非常感謝我用std:string更改了所有char * s,現在它按照我的預期工作。 – merveotesi