2012-10-01 52 views
3

我想分發我的程序作爲二進制文件,而不是源代碼格式。我有兩個測試系統:一個較舊的Linux(帶有glibc 2.10的openSUSE 11.2)和一個最新的Linux(帶有glibc 2.15的LinuxMint 13)。現在,當我編譯LinuxMint系統上我的節目用glibc 2.15,然後嘗試用glibc 2.10啓動的openSUSE系統上的二進制文件,我得到以下兩個錯誤:瞭解glibc

./a.out: /lib/libc.so.6: version 'GLIBC_2.15' not found (required by ./a.out) 
./a.out: /lib/libc.so.6: version 'GLIBC_2.11' not found (required by ./a.out) 

這到底是怎麼迷惑我,這是爲什麼我在這裏也得到「glibc 2.11 not found」錯誤嗎?我希望程序現在需要glibc 2.15,因爲它已經用glibc 2.15編譯過了。爲什麼程序也在尋找glibc 2.11?這是否意味着我的程序將在兩個glibc版本上運行,即2.15和2.11?所以它至少需要2.11?或者在任何情況下都需要2.15?

另一個問題:這個假設是否正確,glibc向上兼容但不是向下?例如。是一個用glibc 2.10編譯的程序,可以保證與任何未來版本的glibc完美搭配?如果是這樣的話,如果像PATH_MAX這樣的常量在將來發生變化會發生什麼?目前它設置爲4096,我使用PATH_MAX常量爲realpath()POSIX函數分配緩衝區。現在,如果將來這個常量提高到8192,那麼可能會出現問題,因爲我的程序只分配了4096個字節。還是我誤解了一些東西?

感謝您的解釋!

+0

嘗試靜態鏈接你的代碼:'gcc -static mycode.c' ... –

+0

另外:在你的問題中有太多的問題。如果只發佈一個明確的問題,你會得到更好的答案。 –

+0

@ DouglasB.Staple:如果你這樣做,你必須分發資源! –

回答

7

Libc使用符號版本控制。這是相當先進的魔術,但基本上每個符號都是根據其出現的版本附加標籤。如果它是語義上的變化,那麼有兩個版本,一個是舊版本的語義,一個是最初出現的版本,另一個是新語義和它出現的版本。加載器只會抱怨程序實際請求的符號。其中一些碰巧在2.15被引入,其中有些恰好在2.11引入。

這是爲了保持glibc向後兼容。這非常重要,因爲有很多打包軟件,它們都是動態鏈接的,重新編譯所有這些都需要很長時間。還有很多軟件沒有可用的源代碼,舊版本的libc可能不適用於新內核或新的其他內容。

所以,是的,glibc是向後兼容的。只要確保您編譯的版本與您需要它運行的最舊版本相同,因爲它不是(也不能)向前兼容。

Ad PATH_MAX:如果完成了這樣的更改,glibc會簡單地導出使用新值的符號的新版本和具有適當安全措施的舊版本符號,以處理針對舊值編譯的代碼。這是所有巫術的主要觀點。

+0

謝謝!有沒有什麼方法可以找出它所引用的2.15的符號?我真的很好奇,因爲我只是使用普通的舊C函數。無法真正想象爲什麼它需要2.15的符號... – Andreas

+0

@Andreas:我相信'ldd'或'objdump'會列出所需的符號,包括它們的版本。 –

+0

@Andreas:某些函數在2.10和2.15之間可能有_changed_。也許一些常數,某種結構的定義或某些事物的確定。所以這個函數在源代碼兼容的時候會有不同的二進制接口。提供了新舊版本,但在編譯時總是會獲得最新的定義。 –