2013-03-22 89 views
1

因此,我繼續瞭解C,並且我有一個有趣的問題。 如果我沒有把錯誤的東西放在堆上,我必須使用malloc等。 但char * str呢? 在什麼內存段將str位於? 我讀過它會放在.bss段(這就是爲什麼你不能在C中改變字符串)。它是否正確?或者將它放在堆棧上?高級C內存分配

如果是的話,爲什麼程序結束時不需要釋放這些內存? 也在每個函數的內存段代碼中?換句話說,指向函數的指針將指向哪個段? 感謝您的幫助! 只是想更好地理解C中的內存管理。

+0

也許這可能會幫助http://stackoverflow.com/questions/14004302/how-c-strings-are-allocated-in-memory?rq=1 – 2013-03-22 17:24:04

+1

聲明'char * str;'只分配一個空間指針對象。如果你想指向一個數組(可能包含也可能不包含字符串),那麼必須通過調用'malloc()',通過使用字符串文字,通過定義數組對象或其他東西。 – 2013-03-22 17:25:46

+0

嗨。我的問題是這個內存在哪裏?在堆棧或BSS段? – Farseer 2013-03-22 17:29:03

回答

4

如果你把一個定義char *str;放在一個函數中,那麼它是一個類型爲「pointer-to-char」的自動變量。

它位於堆棧上,當函數返回時(編譯器通過發送代碼以根據需要移動堆棧指針來處理此堆棧),該堆棧的一部分將變爲未使用。從理論上講,堆棧的存在純粹是一個實現細節,實際上C總是有一個調用堆棧,幾乎所有的實現都或多或少地以相同的方式進行管理,而實際上它是管理的,自動變量存儲的內存是可能被稱爲「堆棧」。

如果你把一個定義char *str;放在任何函數之外,那麼它是一個具有靜態存儲持續時間的全局變量。

它存儲在一個可讀寫的數據段中,當程序退出時可能未被使用(可能操作系統會爲您處理,儘管它原則上可能是編譯器發出的代碼)。由於它是零初始化的(並且假設所有位爲0的空指針所代表的體系結構)是,它可以進入bss段,這是專門用於具有靜態存儲持續時間的零初始化讀寫對象的。同樣,靜態持續時間對象的存儲細節取決於實現,但再一次,這是它通常完成的方式。

這與字符串文字不可修改有關,因爲您尚未定義字符串(更不用說使用字符串字面量了)。你已經定義了一個指針,它可以指向一個字符串,但是還沒有這樣做。

4

如果你只是說char * str數組的內存將不會被分配,只有指針本身的內存。你需要手動分配內存給字符串,可能在堆上,也可能手動釋放它。

「你不能更改C中的字符串」是錯誤的。您不能更改字符串常量,並且字符串常量的分配類似.rodata(只讀部分)。與其他代碼一樣,函數代碼的位置類似.text

2

在C中,所有局部變量將被放入堆棧。變量str是一個字符指針。它包含一個內存地址。在堆棧上將只有這個指針str

char * str; 

這種具有指針(上32/64位4或8個字節)堆棧上的大小分配內存。

str = malloc(1024); 

malloc分配在堆上 1024個字節並返回一個指針,該存儲器區域的第一個字節。該指針保存在位於堆棧上的str中。

當函數(其中str是局部變量)返回時,您的變量str將被釋放。內存區域str指向的內存區域不會自動釋放。您需要使用free(str)手動執行此操作。

字符串可以修改!但不是常量字面值:

char string[4] = "foo"; 
string[0] = 'F'; //will work 

char * stringconst = "foo"; 
stringconst[0] = 'F'; // this will segfault 

上述不會工作,因爲「foo」將被放置(只希望)在readonly內存區域。

2

我認爲你已經混淆了指針和它們指向的內容。藉此:如果多數民衆贊成在文件範圍內聲明的

char *str = "Hello"; 

,然後str是靜態分配的指針。它指向的字符串是完全獨立的。你可以有str指向任何東西。

如果它在函數中聲明,那麼str是分配在堆棧上的指針。再次,文字是分開的。

事實上,如果你有以下兩行:

char *str1 = "Hello"; 
char *str2 = "Hello"; 

的編譯器就可以讓每個指向內存中的同一地址。

無論指針如何,字符串文字都是靜態分配的,並且它(通常)放置在初始化的只讀數據段中。

還要記住,堆棧,堆棧和段的所有概念都與實現完全相關,而不是語言。

0

在C中,我們可以通過字符數組或字符指針指任一字符串。

情況1:如果字符串被稱爲字符數組:

char[] = "storage of strings"; 

如果上述聲明是GLOBAL那麼這被存儲在數據段否則這將被存儲在堆棧段。

案例2:如果字符串被字符指針引用,並且在運行時分配內存(即使用malloc,calloc)。

char *str = (char *)malloc(sizeof(char)*size); 

在這種情況下,存儲器是從HEAP段中分配的。

案例3:如果通過字符指針引用字符串並將字符串值直接賦值給字符指針。

char *str = "storage of strings" 

在這種情況下,這將被存儲在DATA segment.It是像字符串文字被分配在數據段和這個字符串是分配給str變量的地址的存儲器。

PS:每個在運行時分配的內存(HEAP段)都需要在程序本身中釋放。所以如果你使用malloc,calloc或任何在運行時分配內存的函數,你需要使用free()。