2010-09-01 95 views
3

我很驚訝,爲什麼這個工程?C角箱和陷阱

short main [] ={}; 

這是文件中唯一的內容。它在gcc上正確編譯。但是,當我運行它打印分段錯誤。當我重命名主,編譯器給出錯誤。 任何人都可以解釋我在這裏發生了什麼。

+0

我相信,我已經看到了這一個已經,您聲明外部符號主要和連接器沒有按不關心類型。這是不正確的C. – jbcreix 2010-09-01 13:06:28

+1

-1對於問題爲什麼一些有未定義行爲的荒謬代碼「起作用」(在一個非常不好的意義上,不會更少)。 – 2010-09-01 13:18:05

+2

我想有人應該提到這個[IOCCC entry](http://www.ioccc.org/years.html#1984_mullender)。 – 2010-09-01 13:30:44

回答

4

顯然,鏈接器不知道全局對象的類型(如:變量或函數),但只有地址;所以它將程序鏈接起來,就好像你的變量是一個函數一樣。出於顯而易見的原因,這崩潰了。

1

嘗試使用更多選項編譯。 :)

例如添加簡單-Wall

gcc -Wall test.c -o t 
test.c:1: warning: ‘main’ is usually a function 

我沒有看到相關的標準頁,但顯然你就必須有主某種以編譯,不一定是功能.. 。

+0

'gcc -ansi -pedantic -W -Wall' – 2010-09-01 13:16:23

3

你是否得到這樣的錯誤?

Undefined symbols: 
    "_main", referenced from: 
     start in crt1.10.6.o 
ld: symbol(s) not found 
collect2: ld returned 1 exit status 

這不是編譯器錯誤,而是鏈接器錯誤。

在編譯時,每個源文件都被轉換爲一個目標文件。

沒有檢查是否存在int main(),因爲該程序可能由多個來源組成,並且main()僅在其中一箇中定義,或者甚至不需要存在(例如在動態庫中)。由於源

short main[] = {}; 

是由編譯器視爲一個有效的聲明(創建一個全局short陣列命名爲main並初始化爲空數組),也不會產生任何錯誤。

連接器檢查是否存在int main()存在。鏈接器將編譯後的對象文件綁定到可執行文件。如果鏈接器找不到符號main,它會像我上面描述的那樣抱怨。不幸的是,傳統的C ABI沒有區分函數或輸出變量。所以,即使main被聲明爲一個數組,因爲鏈接器只知道「存在一個叫main的東西」,並且不能檢查更多,它也會通過。

結果是程序生成沒有錯誤,雖然它被錯誤地寫入。

程序運行時,所謂main不包含可執行代碼。相反,它只是一些數據(可能爲零)。所以系統可以做任何意想不到的事情(在你的情況下,它是一個SEGFAULT)。與-Wall標誌GCC,這給出了一個警告,編譯時

這實際上可以被捕獲:

<stdin>:1: warning: ‘main’ is usually a function 
+0

好的,我明白了,但是我還有一個問題在我腦海裏浮現,我們能否在這個陣列中寫些東西來做一些有用的事情,比如打印你好。有一個gcc選項fwritablestrings,它會做什麼? – 2010-09-01 15:00:41

+0

short main [] = {}; 我不認爲這是有效的聲明。零初始化器?也許有效的C99? – Nyan 2010-09-01 16:51:11

+0

@Nyan:也許GCC擴展。無論如何,這不是重點。 – kennytm 2010-09-01 17:16:58