不要問我為什么要做我正在做的事情……那將是一個漫長的故事。目前,這篇文章的目的是學習和理解為什么事情沒有按我期望的方式作業。可能我的期望是錯誤的?
所以最初我使用最近的編譯器從源代碼構建我自己的 SystemC 2.3.3 庫,比如gcc 10.2.0。但是,為了保持與舊 gcc 的向后兼容性,我要求 C 11 :
./configure CXXFLAGS="-DSC_CPLUSPLUS=201103L"接下來,我想使用支持 C 11(和相同 ABI)的舊 gcc 構建一個應用程式,比如gcc 8.2.0,:
g -std=c 11 sc_main.cpp -I/path/to/systemc/include -L/path/to/systemc/lib -lsystemc -lm -o sim
令我驚訝的是,鏈接失敗:
libsystemc.so: undefined reference to `std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::basic_stringstream()
實際上,比較的輸出
nm --demangle `/path/to/gcc/10.2.0/bin/g --print-file-name libstdc .so` | grep "std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::"
和
nm --demangle `/path/to/gcc/8.2.0/bin/g --print-file-name libstdc .so` | grep "std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::"
揭示了一些差異。事實上,前者包含std::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::basic_stringstream()而后者不包含。
這是預期的嗎?這是否意味著一般來說,庫的生產者和消費者使用相同的 C 版本(和相同的 ABI)是必要的,但還不夠?還是有其他我不明白的事情發生?
uj5u.com熱心網友回復:
這是否意味著一般來說,庫的生產者和消費者使用相同的 C 版本(以及 > 相同的 ABI)是必要的,但還不夠?
正確的。向后/向前兼容性不僅僅由編譯源代碼時使用的 C 語言版本定義。向后/向前兼容性本身就是一個復雜的話題。但我將給出一個簡單的人為示例來說明一些基本概念。
讓我們簡化一下 astd::string是什么。它基本上是一個指標,以及字串中的字符數:
namespace std {
class string {
char *chars;
size_t nchars;
public:
// Constructors and other methods.
};
}
實std::string數有點復雜(并且會使用為 C 實作保留的符號名稱,但這并不重要)。這只是一個簡化的說明。std::string甚至在 C 11 之前就已經存在。因此,多年來,事情一直在發展,您的 C 編譯器已更新到 C 20。無論出于何種原因,它的 C 庫決定稍微改變這個類:
namespace std {
class string {
size_t nchars;
char *chars;
public:
// Constructors and other methods.
};
}
此時,您可以選擇指示您的新 C 編譯器僅在 C 11 語言版本中進行編譯。這將只允許 C 11 語言功能。但是,生成的二進制代碼仍然不會與由舊版本的 C 編譯器構建的代碼二進制兼容,后者是使用不兼容的類布局編譯的。
一般來說:為了使新編譯器構建的 C 代碼與舊編譯器構建的代碼二進制兼容,需要顯式編譯/配置選項。當然,這可能是指定通用 C 語言版本的選項,但僅僅這樣做通常是不夠的。所做的只是指示編譯器使用哪個語言版本來編譯 C 代碼。較新的語言版本過時/棄用早期版??本的功能,語言選項的目的是允許當前C 編譯器編譯為C 標準的早期版本撰寫的源代碼。這與向后/向前兼容性不同。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/435294.html
