2011-06-17 101 views
4
#include <stdio.h> 
#include <stdlib.h> 


int main(int argc, char * argv[]) 
{ 
    char *p[2]; 
    char **pp = calloc(2, 4); 

    p[0] = "ab"; 
    p[1] = "cd"; 
// p[2] = "ef"; 

    pp[0] = "ab"; 
    pp[1] = "cd"; 
    pp[2] = "ef"; 

    printf("pp: %s, %s, %s\n", pp[0], pp[1], pp[2]); 
    printf("size_p: %d\nsize_pp: %d\n", sizeof p, sizeof pp); 
} 

如果'p [2]'被定義並賦值 - 結果行爲是段錯誤。如果分配了「pp [2]」,則輸出如下:「ab,cd,ef」。 'sizeof'對於'p'返回8(每個指針2×4字節),對'pp'只返回4個字節。爲什麼我能夠分配'pp [2]',儘管它應該只擁有8字節的分配內存(應該只能存儲2個指針地址)?另外,'sizeof'在兩種情況下如何確定實際的內存大小?指針malloc和操作指針

+0

在哪個平臺/ OS上運行此程序?你用什麼libc? – levu 2011-06-17 09:40:02

+1

@levu Ubuntu,x86_64 GNU/Linux,glibc'2.7-10ubuntu7' – XXL 2011-06-17 09:41:11

回答

2

With char *p[2];您在堆棧上分配2 char*。當訪問p[2]時,你有一個緩衝區溢出,並且可能訪問屬於當前方法的棧幀的其他任何fings(一些編譯器在調試模式下檢查這個)。

隨着calloc,你在堆中分配內存。訪問pp[2](可能)是空閒的內存,在這裏你沒有段錯誤。但是這個內存也可以被其他對象使用,所以這絕對不行!

對於大小計算:sizeof(char**)爲4,與每32位指針一樣。 sizeof(char*[2])是8,因爲它是2×4字節。

+0

這似乎是最好的答案,因爲它涵蓋了內存分配的技術方面。謝謝。 – XXL 2011-06-17 10:01:08

4

p被聲明爲有兩個元素,所以p[2]不存在 - 因此segfault。由於p是一個本地數組(指針),因此sizeof(p)給出元素類型的大小(元素類型爲char *,大小爲4)乘以元素數(2)。另一方面,pp是指針(指針),而不是數組,因此sizeof(p)只是char **的大小,它與32位機器上任何其他指針的大小相同,即4 。pp[2]的分配似乎成功是純粹的機會 - 你正在寫入分配的內存之外(其中只包含兩個char *元素的空間)。

順便指出,字符串文字的指針應該是const char *

1

正如Aasmund Eldhuset所說,p [2]不存在。 p [0]和p [1]是數組的兩個元素。

據我所知,p [2]而不是pp [2]的段錯誤原因是因爲p存儲在堆棧中,pp存儲在堆中。因此,儘管您沒有在pp [2]上擁有內存,但它不會造成故障。相反,它只是覆蓋神知道什麼,可能會導致你的程序以不可預知的方式行事不端。

一般來說,動態分配的內存(例如pp中的pp)不會總是出現段錯誤,如果超出了界限,而靜態分配的內存(例如.p)將會出現段錯誤。

+0

我不知道爲什麼人們不斷重複關於p [2]的段落錯誤的事情:)我從來不問爲什麼會發生這種情況,因爲這很明顯。感謝你對king_nak的帖子稍微有些細緻的補充。 – XXL 2011-06-17 10:00:33