類型截斷引起的Bug
背景
最近遇到了一個Bug,由於崩潰堆棧定位到的是一個第三方的so中,查了許久。最終,定位到了出問題的部分。
現象原因:
Model層傳給UI層,一個用於描畫的Buffer。在使用前,該Buffer被異常釋放。導致UI層再調用第三方庫,創建紋理時崩潰。
根本原因:
C++類型截斷導致
類型截斷
- 下面的代碼展示了類型截斷的發生,以及導致Bug發生的現象
// 父類
class Parent
{
public:
void* buffer;
}
// 子類
class Child : public Parent
{
public:
std::shared_ptr<BitMap> buf;
}
// 由於編譯限制,接口層禁止使用C++11。
// 所以在Model層,使用智能指針保存buf
// 爲UI層提供原始指針 buffer
std::map<Parent> m_bufferMap;
void saveBitmap(BitMap* bitmap)
{
Child node;
node.buf.reset(bitmap);
node.buffer = buf.get();
// 將子類賦值給父類類型
// 發生類型截斷
// 導致子類部分的智能指針被釋放
// 給外部用的buffer,此時是一個非法地址了
m_bufferMap.push_back(node)
}
- 上面的例子鍾,將子類對象賦值給父類類型的對象時,會發生類型截斷。子類中多餘的部分,將會被拋棄。
- 那麼如何防止,這種現象?
// 1. 使用指針類型
Parent* p = new Child()
// 2. 對於棧上申請的對象,使用正確的類型保存
std::map<Child> m_map;
Child Node;
map.push_back(Node);
總結
- 問題的原因比較簡單,就是C++的一個基本概念。但是該原因導致的問題,以及定位問題的調查過程,還是比較久的。因此,一定要對語言的基本概念會深刻的瞭解,特別是底層語言,否則很容易自己挖坑。