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

The code is above. I aim to write directory explorer recursively.

I GDBed the code and it reaches return 0 when inspect method called recursively, but return 0 can not be executed. Might it be about stackoverflow caused by some other lines? Any idea would be appreciated.

2
  • It doesn't appear that you ever allocate any space for the strings you are storing. You call malloc(0) in a couple places but allocating space for 0 bytes isn't going to be very useful for you. Commented May 11, 2012 at 16:15
  • 3
    Btw life will be much easier for you if you use std::string (or some other string class) rather than trying to manage string memory yourself via (char *) pointers. Commented May 11, 2012 at 16:16

2 Answers 2

3

On your Element constructor, you're memcpy-ing char arrays without allocating the destination char*. You should consider using 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;

};

You are also performing a malloc of 0 bytes, and then use this pointer as if it was valid:

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

You should also consider using std::string, or at least fix it to allocate a valid amount of bytes.

Sign up to request clarification or add additional context in comments.

3 Comments

thanks very much i did the changes you suggest now the seg fault problem is out dated :)
and can i pass by reference/address with std::string?
Glad it helped. Yes you can pass them using pointers/referenes.
1

Since you're using gdb I'm going to assume valgrind is available. Your use of memcpy is unsafe and valgrind should assist with finding the various memory corruption issues your program seems to have. Like Jeremy Friesner and fontanini both suggested, use std::string instead of naked char *.

1 Comment

thanks very much i changed all the char * s with std:string and now it is working as i expected.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.