#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?任何想法都将不胜感激。
答案 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应该有助于找到你的程序似乎有的各种内存损坏问题。就像Jeremy Friesner和fontanini都建议的那样,使用std :: string而不是naked char *。