2011-11-19 67 views
1

我在接受採訪時被問到了這個問題。什麼是未初始化的指針變量?

如果有聲明,但沒有初始化像這樣的指針: int *ptr;

是它分配一個默認值?或者它會是一個空指針?

if(ptr) { //block of code }

請問如果條件通過:另外,如果我們試圖用這個指針一樣會發生什麼?此外,這將工作在調試/發佈構建?

我試着在家裏運行這個程序,發現if條件的推移,如果我嘗試打印的PTR這樣的值:

printf("%x %d", ptr, *ptr);

它打印一些隨機值,但它不會使程序崩潰。這背後的解釋是什麼?

回答

4

未初始化的指針適用於安全漏洞,並可能有助於播種隨機數生成器。

如果指針已初始化爲NULL(0),則您的if條件將僅跳過該代碼塊。

因爲初始化值默認是未定義的,所以初始化爲NULL總是被認爲是很好的做法。

您的printf語句只是說明了它默認爲NULL以外的值的事實,在這種情況下,它是一個可以取消引用的有效內存區域。

+1

「可能有助於播種隨機數發生器」 - 提供的熵估計值與0一致。 –

+0

並提供了一條評論,指出這是未初始化的原因,因此有人不運行valgrind,初始化爲null並打開一個新的安全漏洞(http://digitaloffense.net/tools/debian-openssl/) –

+2

雖然這很複雜。 Debian的bug涉及一個刪除*兩個操作來添加種子數據的檢查。其中一個貢獻的數據始終未初始化,並導致valgrind/purify錯誤。刪除這是安全的,因爲它不是播種過程的重要組成部分。其他操作貢獻的數據通常不是未初始化的,在初始化的情況下,它對安全性至關重要。但是這條線看起來很像另一條線,所以當另一條線(可能是正確的)被刪除時,它(絕對不正確)也被刪除了。 –

9

如果它是一個全局變量(或static),它將被隱式初始化爲NULL。否則,它的值是未定義的。因此,該if語句的行爲是未定義的(即,您不能假定它可能做什麼)。您的第二個示例的行爲也未定義(並且可能導致分段錯誤)。

未初始化的指針被認爲是危險的;想象一下這段代碼的後果:

int *ptr; 

... 

*ptr = 42; // Dereference pointer and trash somewhere random in memory 

但是請注意,這可能不會崩潰;它可能會悄悄地破壞東西。

所以約定總是明確地初始化它指向一些有用的東西。如果這是不可能的(例如,你還沒有指向的東西),你可以做的下一個最好的事情是將其初始化爲NULL。取消引用NULL指針會在大多數平臺上引發分段錯誤,這至少可以幫助您追蹤錯誤。

+0

謝謝你的回答。我認爲這是有道理的。 – rain

2

什麼是非初始化指針變量的好處?

效率。如果C自動初始化指向NULL的指針,它將浪費整個CPU指令(或者如果變量必須存儲在主存儲器而不是寄存器中,則可能更多),這對於C的設計者是不可接受的。你會相信程序員現在想犧牲寶貴的納秒運行時間來節省幾個小時的調試嗎?

+3

沒有幫助的事實是,在C89中你必須在塊的頂部定義所有的變量,並且(錯誤地是IMO)一種常見的風格是將它們全部定義在函數的頂部。所以人們在變量被初始化之前很久就定義了變量,包括有條件地未使用的變量。出於你說的原因,並且因爲僞初始化可以抑制關於真正未使用的變量的編譯器警告,所以通常很容易定義它們而沒有初始化器。現在你可以在你喜歡的地方定義變量,定義一個有條件的未使用的變量的理由很少。 –

+0

「抑制編譯器警告」 - 示例'int * s = 0,* a = 0; if(condition1){a = value1; } else if(condition2){a = value2; } else if(condition3} {s = value3;/* typo,應該是 - 如果我沒有初始化爲0,我可能會得到關於此分支的編譯器警告* /} printf(「%d \ n」 ,* a);''我的意思是真正未初始化的,沒有真正沒有被使用的...... –

+1

我認爲正交性不僅僅是效率,一般來說局部變量不是爲了效率原因而初始化的(想想大數組),特別是局部指針變量爲正交原因初始化。 – ninjalj