2016-08-13 50 views
-1

我正在用C程序循環訪問我的文件結構。我打了一個新的文件夾,我將它附加到鏈接列表的路徑中,以便我可以反覆查看所有子目錄。C在循環中返回無效地址

該計劃包括:

主要功能,調用迭代函數(通過文件循環)

當我遍歷所有的文件,一旦一切工作正常。但是,當我的主函數中有一個while循環更頻繁地調用迭代函數時,由於分段錯誤,它第二次總是失敗。

所以我正在調查一下,似乎鏈表中的一個元素有一個無效的地址。

我的元素的所有地址具有這種格式和長度:0x2398ff0或0x2398ee0

但是非法指針從0x7f3770304c58地址

沒有人有任何的想法,爲什麼這個地址是這麼長時間?

我已經通過printf(「%p」,元素)檢查了每個添加到鏈接列表的新地址,並且此地址從不出現在代碼中的任何位置。它就像奇蹟般地出現。

我正在考慮一個野生指針也許,但是在我釋放任何指針後,我將它設置爲NULL,這應該防止這種情況發生?

感謝您的任何提示。我現在還沒有發佈代碼,因爲它很長,我想可能有些明顯的東西我只是看不到。

編輯:整個代碼,包括主要功能

#include <stdio.h> 
#include <stdlib.h> 
#include <dirent.h> 
#include <string.h> 
#include <errno.h> 
#include <unistd.h> 

void iterativefile(FILE *f, char** field, int looper){ 

    DIR *d; 
    struct dirent *dir; 

    typedef struct nextpath { // Define element type of linked list 
     char *thispath; 
     struct nextpath *next; 
    }nextpath; 

    nextpath *startpath = malloc(sizeof(nextpath)); 
    char * beginning = (char *) malloc(2); //create first element in linked list, starting on root node "." 
    strcpy(beginning, "."); 
    startpath->thispath = beginning; 

    int found = 0; 

    nextpath *currentzeiger = startpath; 
    nextpath *firstelement = startpath; 
    char *newdir, *currentfile, *currentpath; 

    do { 
     currentpath = currentzeiger->thispath; 
     d = opendir(currentpath); 
     if (!d){ //IF the path is invalid or cannot be opened 

      firstelement = currentzeiger->next; 
      free(currentzeiger); 
      currentzeiger = firstelement; 
      continue; 
     } 
     while((dir = readdir(d)) != NULL){ 
      if (dir->d_type != DT_REG){ // current element is a directory -> add it to linked list 
       if (strcmp(dir->d_name, ".") != 0 && strcmp(dir->d_name, "..") != 0){ 
        newdir = (char *) malloc(2+strlen(currentpath) + strlen(dir->d_name));  
        strcpy(newdir, currentpath); 
        strcat(newdir, "/"); 
        strcat(newdir, dir->d_name); 
        nextpath *new = malloc(sizeof(nextpath)); // add new folder to linked list 
        new->thispath = NULL; 
        new->thispath = strdup(newdir); 
        new->next = currentzeiger->next; 
        currentzeiger->next = new; 
        free(newdir); 
        newdir = NULL;    
       } 
      } 
      else { // current element is a file -> check if already included in list, if not, add it 
       currentfile = (char *) malloc(2+strlen(currentpath)+strlen(dir->d_name)); 
       strcpy(currentfile, currentpath); 
       strcat(currentfile, "/"); 
       strcat(currentfile, dir->d_name); 
       found = 0; 
       if (field != NULL) { 
        for (int z = 0; z < looper; z++){ 
         if (field[z] != NULL){ 
          if(strcmp(currentfile,field[z]) == 0){ 
           found = 1; 
           free(field[z]); 
           field[z] = NULL; 
          } 
         } 
        } 
       } 
       if (found == 0){ 
        char *renamefile = (char *) malloc(strlen(currentpath) + 6); 
        strcpy(renamefile, currentpath); 
        strcat(renamefile, ".cbsm"); 
        free(renamefile); 
        renamefile = NULL; 

       } 
       free(currentfile); 
       currentfile = NULL; 
      } 
     } 

     firstelement = currentzeiger->next; 
     free(currentzeiger->thispath); 
     currentzeiger->thispath = NULL; 
     free(currentzeiger); 

     currentzeiger = firstelement; 
     closedir(d); 

    }while(currentzeiger != NULL); 
} 



int main() 
{ 
    int counterofwhile = 1; 
    while(1){ 
    printf("Loop number: %d\n", counterofwhile); 
    counterofwhile++; 
    FILE *fp = fopen("datasyn.txt", "rw+"); 
    if (fp == NULL) { 
     printf("FILE ERROR"); 
     FILE *fp = fopen("datasyn.txt", "ab+"); 
     iterativefile(fp, NULL, 0); 
    } 
    else { 
     int lines = 0; 
     int ch = 0; 
     int len = 0; 
     int max_len = 0; 
     while((ch = fgetc(fp)) != EOF){ 
      ++len; 
      if (ch == '\n'){ 
       if(max_len < len) 
        max_len = len; 
       ++lines; 
       len = 0; 
      } 
     } 

     if (len) 
      ++lines; 
     fprintf(stderr, "%d lines\n", lines); 
     if (lines > 0){ 
      int numProgs = 0; 
      char *programs[lines]; 
      char line[max_len + 1]; 
      rewind(fp); 
      while(fgets(line, sizeof(line), fp)){ 
       int new_line = strlen(line) - 1; 
       if (line[new_line] == '\n') 
        line[new_line] = '\0'; 
       programs[numProgs++] = strdup(line); 
      } 

      iterativefile(fp, programs, numProgs); 
      for (int j = 0; j < numProgs; j++){ 
      free(programs[j]); 
      } 
     } 
     else { 
      iterativefile(fp, NULL, 0); 
     } 
    sleep(1); 


    printf("Done\n"); 
    fclose(fp); 
    } 

    } 
    return 0; 
} 
+2

嘗試顯示實際的代碼 – oldrinb

+1

」想到也許有一些明顯的東西我只是看不到。「我們也沒有看到他們。 http://stackoverflow.com/help/mcve。你可能會破壞堆棧,或者有其他類型的緩衝區溢出。 – OldProgrammer

+0

您可能正在調用一個採用'char **'的庫函數,並且期望'NULL'哨兵作爲該數組的最後一個元素。你可能沒有提供這個'NULL'哨兵。 – OregonTrail

回答

2

在功能iterativefile(),你不使用calloc()分配startpath,你不設置startpath->next爲空。由malloc()返回的內存不一定歸零。當你隨後使用startpath->next時,所有地獄都會崩潰。

您也不使用傳入iterativefile()的文件指針。當您從定義中刪除參數時,您將更改呼叫,並在main()(在if (fp == NULL)區塊中創建了一個新的FILE *fp,這真的不需要)。真的不清楚還有什麼意思是要發生的;你還沒有給出清楚的指示,說明該程序的意圖。我沒有datasyn.txt文件,但它沒關係,因爲文件流沒有被使用。我從代碼中得到了很多行,如FILE ERRORLoop number: 280,但沒有崩潰,之前我遇到了崩潰。

編譯更多的警告選項。我所謂的文件fp17.c和編譯使用我砍死版本:

gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes \ 
    -Wold-style-definition fp17.c -o fp17 

隨着其他一些簡單的改變(static函數之前; int main(void)),代碼乾淨編譯(並會需要-Wshadow如果它被發現的陰影不是因爲一個'未使用的變量'警告指出了我)。「

+0

嘿喬納森!非常感謝您的回答。使用calloc而不是malloc真的有竅門!謝謝! – Tom