2011-10-05 54 views
1

讀書時,我有以下功能:分段故障從文件

void read_file(char* path, char** data) 
{ 
    FILE* file = NULL; 
    size_t size, result = 0; 

    *data = NULL; 
    file = fopen(path, "rb"); 

    if (file == NULL)// error opening file 
    { 
     return; 
    } 

    fseek(file, 0, SEEK_END); 
    size = ftell(file) + 1; 
    rewind(file); 

    *data = (char*)malloc(size); 
    if(*data == NULL) 
     return; 

    result = fread(*data, 1, size, file); 
    if (result != size - 1)// error reding file 
    { 
     *data = NULL; 
    } 
    printf("LINE=%u\n", __LINE__); 
    (*data)[size-1] = '\0'; 

    printf("LINE=%u\n", __LINE__); 
    fclose(file); 
    return; 
} 

我正在上線分段故障右兩個printf("LINE=%u\n", __LINE__);語句之間。我不明白這是爲什麼。當我在看這條線時,看起來(*data)將會有一個類型(char *),這當然應該能夠與索引運算符[]一起使用。

我錯過了什麼?

+4

C或C++?選一個(C)。 –

+2

您是否在調試器中輸出了'size'的值?特別是,檢查它不是'0'。 –

+0

這是不是一個有效的功能? –

回答

5

也許if (result != size - 1)測試失敗,然後重置*dataNULL(這是內存泄漏,BTW),然後嘗試寫入(*data)[size-1] - 哎呀!

1

一些指針:

FTELL返回-1失敗,所以如果是這樣的話,這將是0 size = ftell(file) + 1;

的size_t在一些平臺上是unsigned int類型,它可能是件好事,這一點。

*data = NULL;是不是一個好主意,釋放它首先free(*data);

放一些,如果在你的代碼語句來捕獲錯誤,不承擔一切都會 例如assert(size>0);

0

我測試了你的代碼,它適用於我 - 我已經添加了文件大小的返回,以正確地將數據傳遞給fwrite。

> ./a.out arm-2010.09-good.tar.bz2 | sha1sum && sha1sum arm-2010.09-good.tar.bz2 
alloc size of 37265592 
6bdff517bcdd1d279fc84ab3a5fbbca34211a87c - 
6bdff517bcdd1d279fc84ab3a5fbbca34211a87c arm-2010.09-good.tar.bz2 

此外Valgrind報告沒有警告和錯誤,所以.. loooks OK!

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

size_t read_file(char* path, char** data) 
{ 
    FILE* file = NULL; 
    size_t size, result = 0; 

    *data = NULL; 
    file = fopen(path, "rb"); 

    if (file == NULL)// error opening file 
    { 
     return 0; 
    } 

    fseek(file, 0, SEEK_END); 
    size = ftell(file) + 1; 
    rewind(file); 

    fprintf(stderr, "alloc size of %i\n", size); 
    *data = (char*)malloc(size); 
    if(*data == NULL) 
     return 0; 

    result = fread(*data, 1, size, file); 
    if (result != size - 1)// error reding file 
     *data = NULL; 
    (*data)[size-1] = '\0'; 
    size--; // report file size 

    fclose(file); 
    return size; 
} 

int main(int argc, char** argv) 
{ 
    char* data; 
    if(argc<2) 
     return 0; 
    size_t siz = read_file(argv[1], &data); 
    if(data) { 
     fwrite(data, 1, siz, stdout); 
     free(data); 
    } 
    else { 
     fprintf(stderr, "No data returned\n"); 
    } 
    return 0; 
} 
0

這裏的問題的可能來源:

if (result != size - 1)// error reding file 
{ 
    *data = NULL; 
} 
printf("LINE=%u\n", __LINE__); 
(*data)[size-1] = '\0'; 

會發生什麼,如果有錯誤讀取文件?您將*data設置爲NULL,然後立即嘗試解引用它 - 糟糕的juju。

請注意,這也會導致內存泄漏;你不會釋放*data指向的內存。

重構代碼,以便(*data)[size-1] = '\0'只執行如果讀操作成功:

if (result != size - 1) 
{ 
    free(*data); 
    *data = NULL; 
} 
else      
{      
    (*data)[size-1] = 0; 
}