簡體   English   中英

釋放c中的char指針會導致segfault

[英]freeing char pointer in c causes segfault

主題說了全部,這是用簡單文件編寫的相關代碼。

char* fn = NULL;
SDL_Log("fn pre address is: %p\n",fn);
fn = get_resource("test.txt");
SDL_Log("fn pos address is: %p\n",fn);
//free(fn); <--this causes seg fault if I uncomment it

INFO: fn pre address is: 0x0
INFO: fn pre address is: 0x7fa882501a00
INFO: fn pos address is: 0x7fa882501a00

get_resource(const char* filename) {
    char* string = (char*)calloc(1, sizeof(strlen(res_dir) + strlen(filename)));
    //i also tried with strncpy
    //strncpy(string, res_dir, strlen(res_dir));
    //strncpy(string + strlen(res_dir), filename, strlen(filename));

    memcpy(string, "/usr/test/files", strlen(res_dir));
    memcpy(string + strlen("/usr/test/files"), filename, strlen(filename));
    string[strlen(filename) + strlen("/usr/test/files")] = '\0';
    return string;
}

得到相同的行為。 如果釋放分配的字符串,將出現段錯誤。 而且這也不總是總是發生,這很奇怪。

char* string = (char*)calloc(1, sizeof(strlen(res_dir) + strlen(filename)));

這行沒有任何意義, sizeof是用於確定類型或某種類型的表達式所需的存儲大小的運算符。(*)

您想要的是這樣的:

char* string = calloc(1, strlen(res_dir) + strlen(filename) + 1);

注意那里的+ 1 ,它為c樣式字符串中的終止0字節保留空間。 還請注意,強制轉換void *指針(由malloc()和C中的朋友返回)是沒有意義的。 在C ++中這是必需的,但是在C中, void *通用指針類型,並且隱式轉換為任何其他數據指針類型。

進一步挖掘您的代碼(按照alk的注釋)...我想res_dir只是"/usr/test/files" 您可能在此處缺少斜杠(取決於filename的內容),但通常,對於串聯字符串,已經有C語言的函數在string.h聲明。 只需編寫如下簡單內容:

char* string = calloc(1, strlen(res_dir) + strlen(filename) + 1);
strcpy(string, res_dir);
strcat(string, filename);

到此為止。 注意,您甚至不需要使用此方法的calloc()malloc()會很好。


(*)在此處添加更多說明:由於明顯的原因,您可能會看到sizeof經常與內存分配一起使用。 您要為char類型保留內存。 您希望將一些char容納到此內存中。 因此,正確的公式如下所示:

malloc( (strlen(res_dir) + strlen(filename) + 1) * sizeof(char) )

那為什么要忽略sizeof(char)呢? 這是因為char的大小實際上定義1 x * 1仍然是x ,因此無需在此處使用sizeof :)

首先這句話

char* string = (char*)calloc( 1, sizeof(strlen(res_dir) + strlen(filename)));

是不正確的。 表達

sizeof(strlen(res_dir) + strlen(filename))

相當於

sizeof( size_t )

可以等於4或8,具體取決於使用的環境。 有關此表達式的更多信息

sizeof(strlen(res_dir) + strlen(filename))

沒有被評估 也就是說,該表達式中未調用 strlen函數。

正確的陳述看起來像

char *string = calloc( strlen( res_dir ) + strlen( filename ) + 1, sizeof( char ) );

考慮到您還需要為終止的零保留內存。

但是,即使此語句也不正確。

考慮你想做什么

memcpy(string, "/usr/test/files", strlen(res_dir));
memcpy(string + strlen("/usr/test/files"), filename, strlen(filename));

當您傳遞字符串"test.txt"您將獲得

"/usr/test/filestest.txt"

我想你的意思是以下

"/usr/test/files/test.txt"

如果是這樣,那么內存分配必須看起來像

char *string = calloc( strlen( res_dir ) + strlen( filename ) + 2, sizeof( char ) );

在這種情況下,您可以簡單地編寫

strcpy( string, "/usr/test/files" );
strcat( string, "/" );
strcat( string, filename );

在這種情況下,

string[strlen(filename) + strlen("/usr/test/files")] = '\0';

必須刪除。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM