递归分段故障

时间:2012-05-11 16:09:08

标签: c++ recursion segmentation-fault

#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方法时它到达inspect,但return 0无法执行。可能是由于其他一些线路导致的stackoverflow?任何想法都将不胜感激。

2 个答案:

答案 0 :(得分:3)

Element构造函数中,您在不分配目标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 {0}字节的malloc,然后使用此指针,就好像它是有效的一样:

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

您还应该考虑使用std::string,或者至少修复它以分配有效的字节数。

答案 1 :(得分:1)

由于您正在使用gdb,我将假设valgrind可用。你使用memcpy是不安全的,valgrind应该有助于找到你的程序似乎有的各种内存损坏问题。就像Je​​remy Friesner和fontanini都建议的那样,使用std :: string而不是naked char *。