2017-03-07 83 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