2009-06-05 75 views
0

我有下面的代碼片段,它在'str'中的分配期間崩潰,這是一個動態分配。爲什麼此代碼在動態分配期間崩潰?

char *str; 
    int file_size; 
    FILE *fptr; 
    if (!(fptr = fopen(filename, "r"))) goto error1; 
    if ((fseek(fptr, 0L, SEEK_END) != 0)) goto error2; 
    if (!(file_size=ftell(fptr))) goto error2; 
    if ((fseek(fptr, 0L, SEEK_SET) != 0)) goto error2; 
    str = (char*)malloc(file_size+1); 
    if (fread(str, file_size, 1, fptr) != 1) { 
    free(str); 
    goto error2; 
    } 
    str[file_size] = '\0'; 
    fclose(fptr); 

FILE_SIZE是非零,非負少-140值

我使用ARM。這實際上在我的intel電腦上運行,但不是在arm機器上運行。

+0

在分配之前,file_size會給你什麼? – karlipoppins 2009-06-05 09:18:48

+0

其非零值,非負值。 – giantKamote 2009-06-05 10:15:14

+0

這也許可以幫助你:http://xkcd.com/292 – Kieveli 2009-06-05 11:31:18

回答

7

你可以在手冊中看到這個 - ftell()在錯誤中返回-1,而不是零。

3

打印您的變量出來,特別是file_size,然後再使用它們。你可能會感到驚訝。

2

什麼是價值,由ftell(fptr)返回? 也許它太大了? 如果它返回long int indeed,那麼它可能會溢出你的int,你會得到一個負值。

0

在一般意義上...我沒有意思在所有來砸,但你的代碼是有點可怕。使用編碼標準通常會讓你的事情變得更加清晰......也就是說,尼爾可能會得到答案。

2

malloc需要參數size_t。 size_t是unsigned int或unsigned long的typedef(取決於平臺),這裏的關鍵字是UNSIGNED。

您使用的是FILE_SIZE一個int和一個int可能只是16位(您使用的是ARM,所以我會覺得這是一個MCU)。一個有符號的16位只能以字節爲單位支持32,768個字節的文件大小,所以,如果你有一個大的文件(實際上不是那麼大,大於32K),file_size會溢出。

我認爲編譯器告訴你,但你選擇忽略它......現在mallow接受一個無符號參數,所以它會自動轉換你對signedize的文件大小+ 1的評估(即使它深深地溢出了,負面)並嘗試分配內存。 這可能意味着你試圖分配太多的內存比這個嵌入式應用程序。不能有(不應該墜毀)。

我實在不明白了崩潰的一個原因(不是一個壞的庫,它在嵌入式C是常見的,由於低的用戶基礎反饋等),但我看到,導致不必要的行爲的錯誤。

我還沒有去問「爲什麼轉到東西」,「引起的答案將會引發大量的火焰評論。

1

某處你緩衝在不適當的地址溢出或free()之前!!! - )

0

這是不可能的,這是你的問題,但是你要記得

#include <stdlib.h> 

從而使malloc的原型在範圍內?在這種情況下,編譯器不會警告你,因爲它的返回值是無意義的。在C中,沒有理由來施放malloc的返回值。所以:

str = malloc(file_size + 1); 

順便說一句,空白是免費的。

最後,你應該以二進制模式,如果你希望能夠在多個平臺上推斷其大小這種方式打開該文件。基於

str[file_size] = '\0'; 

你似乎隱含假設文件不能包含嵌入的\ 0字符。如果你真的做到了,那我覺得這是一個危險的假設。