2010-07-08 81 views
1

我想知道靜態變量或函數如何被保護,只用於它定義的文件。我知道這樣的變量和函數是在數據部分(堆區確切地說),但它是用文件名標記的嗎?假設我通過將這樣一個靜態函數(在foo.c中定義)分配給全局函數指針,並在其他文件(bar.c)中調用該函數指針,來編譯編譯器的愚蠢。顯然,我的代碼不會給出任何編譯警告,但順便說一句,它給出了分段錯誤。顯然,這是一個保護錯誤,但我有興趣知道它是如何在系統內實現的。如何保護靜態函數/變量

謝謝。 MS

+3

通過函數指針調用另一個編譯單元中的靜態函數不應該導致保護錯誤。發佈您的代碼。 – 2010-07-08 10:17:30

+0

爲什麼會有需要愚弄編譯器,當它實際上是一種爲程序員提供的功能? – 2010-07-08 10:35:27

回答

2

靜態的目的不是爲了「保護」變量/函數,而是爲了保護名稱空間,並保護程序的其他部分免受名稱衝突符號的干擾。它還允許更多的優化,因爲編譯器知道它不需要通過外部模塊訪問符號名稱。

5

鏈接器負責限制函數名稱映射到函數的範圍。

函數指針調用的靜態函數沒有保護 - 這並不罕見。例如,推薦的GObject方法的實現方式是公開一個指向靜態函數的指針(參見GObject how-to中的虛擬公共方法部分)。

3

它被'保護',僅僅是因爲不知道它的符號/位置鏈接器。所以你不能在另一個模塊中寫代碼,因爲鏈接器沒有這樣的符號,所以它的符號名稱明確地引用了靜態對象。沒有運行時保護。

如果您在運行時將某個地址傳遞給某個其他模塊的靜態對象,那麼您將可以通過這樣的指針訪問它。這不是「編制愚蠢的編譯器」(或者實際上是鏈接器),這樣的行爲可能是完全合法的。

事實上,你有一個seg-fault可能是一個完全不同的原因(例如一個無效的指針)。編譯器可能選擇內聯代碼,在這種情況下指向它的代碼將不可行,但是如果你明確地使用了對象的地址,編譯器應該實例化它,所以這看起來不太可能。

0

如果將foo.c和bar.c編譯爲不同的動態加載庫,那麼您可能會遇到問題。

+0

請詳細說明 – 2010-07-08 11:46:45