2015-07-01 57 views
0

我對C和內存分配一般都很陌生。基本上我想要做的是複製一個未知大小的輸入文件的內容,並使用遞歸來反轉它的內容。我覺得我非常接近,但是當我試圖將我認爲是文件反轉內容的內容放入內容中時(我認爲我認爲我做對了......) )fputs上的分割錯誤

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

int recursive_back(char **lines, int lineNumber, FILE *input) { 

    char *input_line = malloc(sizeof(char) * 1000); 
    lines = realloc(lines, (lineNumber) * 1000 * sizeof(char)); 
    if(fgets(input_line, 201, input) == NULL) { 
     *(lines + lineNumber) = input_line; 
     return 1; 
    } 
    else { 
     printf("%d\n", lineNumber); 
     return (1+recursive_back(lines, ++lineNumber, input)); 

    } 

} 

void backward (FILE *input, FILE *output, int debugflag) { 
    int i; 
    char **lines;       //store lines in here 
    lines = malloc(1000 * sizeof(char *)); //1000 lines 

    if(lines == NULL) {   //if malloc failed 
     fprintf(stderr, "malloc of lines failed\n"); 
     exit(1); 
    } 

    int finalLineCount, lineCount; 
    finalLineCount = recursive_back(lines, 0, input); 

    printf("test %d\n", finalLineCount); 

    for(i = finalLineCount; i > 0; i--) {  
     fputs(*(lines+i), output);   //segfault here 
    } 

} 

我正在使用一個簡單的輸入文件來測試代碼。我的輸入文件是6行,表示「這是一個測試輸入文件」。實際的輸入文件正在另一個函數中打開並傳遞給後向函數。我已經驗證了我的程序中的其他功能工作,因爲我一直在玩各種不同的選項。這兩個功能是我遇到的唯一功能。我究竟做錯了什麼?

+0

分配給「行」時,您濫用'realloc'(您已經爲1000個指針添加了足夠的空間)。無論如何,如果你真的要在你的函數中重新分配'lines',那麼它需要是一個三重指針(即'char *** lines',並且你分配給'* lines')或者改變在呼叫者中將不可見。 – ooga

+0

segfault時的finalLineCount被標記爲7(比我的文件的總輸入行數多1)。 – easver

回答

0

你的問題是在這裏:

lines = realloc(lines, (lineNumber) * 1000 * sizeof(char)); 

完全一樣@ooga說。至少有三個獨立的事情不妥:

  1. 您重新分配的內存塊指向recursive_back()局部變量lines,並保存新的地址(假設重新分配成功)回那個局部變量。新的位置不一定與舊的位置相同,但唯一的指針是在recursive_back()末尾超出範圍的局部變量。調用者的相應變量不會更改(包括調用者本身爲recursive_back()時),因此在recursive_back()返回後不再依賴它成爲有效指針。

  2. 您使用錯誤的類型分配空間。 lines的類型爲char **,因此它指向的對象的類型爲char *,但您預留的空間將基於char的大小。

  3. lineNumber爲零時,至少在第一次通話時,您並未預留足夠的空間。在那個調用中,當請求的空間正好是零字節時,realloc()的效果是免費lines指向的內存。在隨後的通話中,分配的空間總是少於您認爲分配的一行。

它看起來像realloc()是完全不必要的,如果你能依靠輸入到至多1000行,所以你應該考慮只刪除它。如果你真的需要能夠以呼叫者將看到的方式重新分配,則呼叫者需要將指針傳遞給它的變量,以便recursive_back()可以通過該指針來修改它。