2017-03-07 45 views
2

我正在使用Linux Ubuntu 16.04上的C++文件搜寻器。

基本上它应该通过一个目录,将文件字节大小添加到链接列表并相应地创建新节点。所以如果我有一个文件夹里面有好几个文件,它就可以算好了

我的问题是,如果我有一个文件夹中有另一个文件夹,我得到一个segementation错误,当用GNU-debugger测试时如下所示:
Segfault用于嵌套文件夹调用

Program received signal SIGSEGV, Segmentation fault. __strcpy_sse2_unaligned() at ../sysdeps/x86_64/multiarch/strcpy-sse2-unaligned.S:714 714 ../sysdeps/x86_64/multiarch/strcpy-sse2-unaligned.S: No such file or directory.

根据stack overflow post 1我需要以某种方式安装库,但没有与安装了正确的版本问题。

我不认为这是我的问题,因为发生故障的位置,根据调试器,它发生在递归函数内部时,它应该挖掘目录并获取数据。在我的主循环中调用相同的函数来遍历顶层目录,它在单层上工作正常,当我有嵌套的目录时,我遇到了问题。附件为基准的完整源代码,这是一个有点长,但如果调用相同参数的错误应该是很容易复制:

// Directory crawler 
// Written by Kaz 

/* 
     1) Start at a user provided directory 
     2) Descend the file tree while tracking each file 
     3) Groups each file by it's size based off user argument 
     4) Print a histogram of file sizes in a bin wide groupings 
*/ 

#include<iostream> 
#include <dirent.h> 
#include<string.h> 
#include <errno.h> 
#include <stdio.h> 
#include<string> 
#include <stdint.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include<stdlib.h> 
using namespace std; 

int binCount = 0; // count of total bins 

struct node{ 
    node* next, *prev; 
    int count, name, min, max; 
    node(){ 
     prev = NULL; 
     next = NULL; 
     count = 0; 
     name = binCount; 
     min = 0; 
     max = 0; 
    } 
}; 


node *nextNode(node* previousNode){ 

     node *nextLink = new node; 
     nextLink ->name = binCount; 
     nextLink->prev = previousNode; 
     nextLink->next = NULL; 
     nextLink->count = 1; 
     nextLink->min = previousNode->max + 1; 
     nextLink->max = ((previousNode->max)*2) + 1; 
     previousNode ->next = nextLink; 
     return nextLink; 
} 

void traverseNewDirectory(node * here, char *dirName){ 
    DIR * nwd; 
    struct dirent *dip; 
    node * current; 
    current = here; 
    bool isadirectory,isHidden; 
    if((nwd = opendir(dirName))== NULL){ 
     perror("Can't open derived directory"); 
     return; 
    } 

    while ((dip = readdir(nwd)) != NULL){ 
     isadirectory = false; 
     isHidden = false; 
     if((dip -> d_type) == DT_UNKNOWN){ 
      struct stat stbuf; 
     stat(dip->d_name, &stbuf); 
     isadirectory = S_ISDIR(stbuf.st_mode); 
     } 
     else if((dip -> d_type) == DT_DIR){ 
      if((strcmp(dip->d_name, ".") == 0) || (strcmp(dip->d_name, "..")) == 0){ 
       isHidden = true; 
       isadirectory = true; 

      } 
      else{ 

       isadirectory = true; 
      } 
     } 
     else{ 
      if((dip-> d_reclen <= current->max)&&(dip->d_reclen >=current->min)){ 
        current->count = current->count+1; 
      } 
      else if(dip->d_reclen < current->min){ 
       node*temp = current->prev; 
       while(temp->prev != NULL){ 
        if((dip-> d_reclen <= current->max)&&(dip->d_reclen >=current->min)){ 
          current->count = current->count+1; 
          break; 
        } 
        else if(dip->d_reclen < current->min){ 
         temp = current->prev; 
       } 
      } 
     } 
      else{ 
       current -> next = nextNode(current); 
       current = current -> next; 
       binCount++; 
      } 
     } 
     if(isadirectory){ 
      char *path; 
      strcpy(path,dirName); 
      strcat(path, "/"); 
      strcat(path,dip->d_name); 
      strcat(path, "\0"); 
      if(isHidden == true){ 

      } 
      else{ 
      traverseNewDirectory(current, path); 
      } 
     } 
    } 
    while ((closedir (nwd) == -1) && (errno == EINTR)); 
} 
void printHistogram(node *head){ 
    node*temp; 
    temp = head; 
    while(temp!=NULL){ 
     cout << "[B " << temp->name << "] from " << temp->min << " to " << temp->max << " : "; 
     for(int i = 0; i < temp->count; i++){ 
      cout << "x"; 
     } 
     cout << endl; 
     temp = temp->next; 
    } 
} 
int main(int argc,char *argv[]){ 
    // Ensures that a valid directory is provided by the cmd line argument 
    if (argc != 3){ 
     if(argc == 1){ 
      fprintf (stderr, " argc = %d no directory given \n", argc); 
      return 1; 
     } 
     else if(argc == 2){ 
     fprintf (stderr, " argc = %d no size given \n", argc); 
     return 2; 
     } 
     else{ 
      fprintf(stderr, "argc = %d invalid parameters \n", argc); 
      return 3; 
     } 
    } 
    DIR * cwd; // current working directory pointer 
    struct dirent *cwdP; // pointer to dirent struct 
    int binWidth; // variable for the width of the grouping in the histogram 
    binWidth = atoi(argv[2]); 
    node *first = new node; 
    binCount++; 
    first->max = binWidth - 1; 
    node * current; 
    current = first; 
    bool isadirectory,isHidden; 
    if((cwd = opendir(argv[1]))== NULL){ 
     perror("Can't open main directory"); 
     return 2; 
    } 

    while ((cwdP = readdir(cwd)) != NULL){ 
     isadirectory = false; 
     isHidden = false; 
     if((cwdP -> d_type) == DT_UNKNOWN){ 
      struct stat stbuf; 
      stat(cwdP->d_name, &stbuf); 
      isadirectory = S_ISDIR(stbuf.st_mode); 
     } 
     else if((cwdP -> d_type) == DT_DIR){ 
      if((strcmp(cwdP->d_name, ".") == 0) || (strcmp(cwdP->d_name, "..")) == 0){ 
       isHidden = true; 
       isadirectory = true; 

      } 
      else{ 

       isadirectory = true; 
      } 
     } 
     else{ 
      if((cwdP-> d_reclen <= current->max)&&(cwdP->d_reclen >=current->min)){ 
        current->count = current->count+1; 
      } 
      else if(cwdP->d_reclen < current->min){ 
       node*temp = current->prev; 
       while(temp->prev != NULL){ 
        if((cwdP-> d_reclen <= current->max)&&(cwdP->d_reclen >=current->min)){ 
          current->count = current->count+1; 
          break; 
        } 
        else if(cwdP->d_reclen < current->min){ 
         temp = current->prev; 
       } 
      } 
     } 
      else{ 
       current -> next = nextNode(current); 
       current = current -> next; 
       binCount++; 
      } 
     } 
     if(isadirectory){ 
      char *fullPath; 
      strcpy(fullPath,argv[1]); 
      strcat(fullPath,"/"); 
      strcat(fullPath,cwdP->d_name); 
      strcat(fullPath, "\0"); 
      if(isHidden == true){ 

      } 
      else{ 
      traverseNewDirectory(current, fullPath); 
      } 
     } 
    } 
    while ((closedir (cwd) == -1) && (errno == EINTR)); 
    printHistogram(first); 
    return 0; 
} 
+1

'char * path; strcat(路径,“/”);'你期望做什么? 'path'是单元化的并且包含垃圾。所以你正在写垃圾场。在尝试写入之前,'path'需要指向一个有效的内存缓冲区。 – kaylum

+0

@kaylum对不起,请忽略'strcat(path,“/”);'我把它放进来测试我是否先串联,如果这样可以消除'strcpy()'发生故障的问题。我只是编辑了我的问题 – Callat

+1

同样的事情,但。 'strcpy'不会为你分配内存。它期望你已经做到了。 – paddy

回答

1

不,这是你的错;)

,它出现segfaults的事实strcpy是构建路径时没有分配任何内存的直接赠品(或者您没有足够的内存用于该字符串,或者不太常见的是您在其他地方有堆损坏)。所以,看看你这样做的两个地方:

 char *path; 
     strcat(path, "/"); 
     strcpy(path,dirName); 
     strcat(path, "/"); 
     strcat(path,dip->d_name); 
     strcat(path, "\0"); 

你最好为此分配足够的内存。目前,您只是根据您从未初始化为path的值将字符串复制到未知内存位置。

真的,我不知道你为什么用C++编写类C代码。你正在使用C++。所以只需使用std::string,它为您处理内存管理。即使这可能会做:

std::string path = std::string(dirName) + "/" + dip->d_name; 

然后,您可以通过访问C字符串递归:

traverseNewDirectory(current, path.c_str()); 

可能还有其他的问题,你的代码了。我没有花时间去阅读它,但是它在使用指针上看起来相当沉重,几乎没有评论,而且过于复杂。所有这些都是麻烦的成分。

+0

我使用'char *'与'opendir'和'readdir'系统调用兼容。从我阅读的内容来看,我需要这些才能使其发挥作用。和路径是为'traverseNewDirectory(current,path);'。它应该工作的方式是,如果我有一个文件夹'test',并且找到另一个名为'nest1'的目录。打开'test/nest1'并将其文件大小添加到链接列表中 – Callat

+1

当然,但您似乎也并不了解内存,而这不是您编写C++代码的方式。我编辑了我的答案,详细说明如何使用'std :: string'作为可用的插入替换。 – paddy

+0

hmmm我收到以下错误:'prog2.cpp:在函数'void traverseNewDirectory(node *,char *)': prog2.cpp:117:44:错误:从'const char *'无效转换为'char * '[-fpermissive] traverseNewDirectory(current,path.c_str());'我认为这是因为我需要修改'traverseNewDirectory()'的任何建议的原型? – Callat