C++二進位制相容問題及解決方法
二級制相容
二進位制相容ABI(application binary interface)主要指動態庫檔案單獨升級,現有用到老動態庫的應用程式是否受到影響。
二進位制相容:
1 升級庫檔案,不影響使用庫檔案的程式。
2 新庫必然有新標頭檔案,但是舊的二進位制可執行檔案還是按照舊的標頭檔案中的“使用說明”來呼叫庫。
UseSharedLibrary.exe SharedLibrary.dll
二進位制不相容示例
1 類的普通成員函式 void f( int ) 改成了 void f( double ) 。老EXE會傳int進來,新庫會用double的長度取資料。從而發生undefined symbol
2 基類增加虛擬函式會導致基類虛表發生變化。老EXE呼叫虛表的時候給出的slot是老的,但是新庫裡面的這個slot已經是另一個函式了。
3 給函式增加預設引數
4 增加預設模板型別
5 改變enum的值
6 給class Bar增加資料成員導致sizeof(Bar)的值變大
7 如果EXE裡呼叫new Bar,導致new出來的記憶體盛不下新的Bar物件(建構函式會使用新DLL中的建構函式來填充資料),從而:
1)如果新的庫實現訪問了新的資料成員肯定會訪問到一個無法預知的地方;
2)如果EXE得到的是shared_ptr<Bar> 由DLL來管理記憶體,那麼此時是安全的。
3)如果EXE呼叫的是p->member 那麼肯定不對,因為偏移量可能因為member前面插入了新的成員而被新DLL中建構函式填充了新的成員,從而訪問的並不是老的member。
4)如果EXE是使用p->get_member()來獲取資料,那麼是正常的。
5) 如果p->get_member()是inline的,那麼是不安全的,因為偏移量已經在EXE中了。
8 虛擬函式做介面的基本上都是二進位制不相容的。
二進位制安全的場景:
1 增加新的class(定義在新DLL中,老的EXE裡沒有)
2 增加非virtual函式(定義在新DLL中,老的EXE裡沒有)
3 增加static成員函式(定義在新DLL中,老的EXE裡沒有)
解決辦法之pimpl技法:
1 標頭檔案只暴露非virtual函式,class的大小固定為sizeof(Impl*)
//標頭檔案
class Graphics
{
public:
Graphics();
~Graphics();//不能是虛擬函式
void f1(void);
void f2(int);
void f3(int, int);//增加成員函式可以直接新增非virtual函式,不影響二進位制相容
private:
class Impl;//標頭檔案只放宣告,sizeof(Graphics)不會變化,成員變數的擴充在Impl中新增
boost::scoped_ptr<Impl> m_impl;//sizeof(Graphics) == sizeof(Graphics::Impl*)
}
//庫的原始檔
Graphics::Graphics()
:m_imp(new Impl)
{
}
Graphics::~Graphics()
{
}
void Graphics::f1(void)
{
m_impl->f1();//呼叫轉發
}
繼承和虛擬函式是萬惡之源
1 繼承體系一旦形成,調整起來就開始費勁。
2 Go語言沒有繼承
C++介面的終極方案
設計模式(四)std::function介面程式設計徹底取代抽象工廠和工廠方法
https://blog.csdn.net/calmreason/article/details/50903729
相關文章
- KDE設區--C++的二進位制相容問題C++
- 二進位制方式解決 power 問題
- 二進位制轉十進位制快速方法
- 進位制詳解:二進位制、八進位制和十六進位制
- 負數的二進位制數問題
- 進位制與二進位制及相關轉換
- C++輸入十進位制數,輸出對應二進位制數、十六進位制數C++
- 二進位制修復中文亂碼的問題
- 二進位制與二進位制運算
- 二進位制陣列 subarray() 方法陣列
- JS操作二進位制方法 - blobJS
- 二進位制補碼及與原碼的互相轉換方法詳解
- JavaScript 二進位制、八進位制與十六進位制JavaScript
- Python處理十六進位制與二進位制轉換的問題——binascii自帶庫PythonASCII
- 二進位制
- (二進位制)
- 十進位制——二 (八、十六 )進位制
- 二進位制,八進位制,十進位制,十六進位制的相互轉換
- 【進位制轉換】二進位制、十六進位制、十進位制、八進位制對應關係
- Spring ApplicationListener使用方法及二次呼叫問題解決SpringAPP
- 二進位制、十進位制與十六進位制相互轉化
- java中二進位制、八進位制、十進位制、十六進位制的轉換Java
- 二進位制,八進位制,十進位制,十六進位制之間的轉換
- 計算機基礎進位制轉換(二進位制、八進位制、十進位制、十六進位制)計算機
- JAVA 二進位制,八進位制,十六進位制,十進位制間進行相互轉換Java
- C++ 讀取二進位制檔案到char*C++
- Nacos 常見問題及解決方法
- 什麼是二進位制?二進位制如何轉換?
- 04 二進位制
- Cocoapods 二進位制
- leetcode -- 二進位制LeetCode
- 解決ie相容性問題
- 解決CSS position:fixed 相容問題CSS
- 基礎問題:進位制轉換
- 二進位制運算子按位與 & 巧妙解決核取方塊的
- 十進位制轉二進位制推導(草稿)
- JavaScript十進位制轉換為二進位制JavaScript
- [計算機基礎] 計算機進位制轉換:二進位制、八進位制、十進位制、十六進位制計算機
- 進位制之間的轉換之“十六進位制 轉 十進位制 轉 二進位制 方案”