[英]Pointer offset is incorrect when using multiple inheritance
我在訪問成員變量時使用多個 inheritance 的某些代碼中遇到錯誤。 不幸的是,我無法提供您可以運行的最小可重現示例,但我可以提供一堆關於我所看到的信息。 我的代碼使用 GCC 編譯為 ARM。
粗略地說,這就是我所擁有的(不是我的實際代碼):
class Foo;
class MyClass:
public A,
public B,
public C
{
public:
Foo& foo() {
assert(_ptr);
return *_ptr;
}
private:
//A bunch of other members
std::unqiue_ptr<Foo> _ptr; //Located 0x2710 from start of this
};
其中類 A、B 和 C 也從其他類多重繼承。 例如:
class A :
public Q,
public R,
public S
{
//Data members and functions...
};
我有一個指向 MyClass 的指針,如下所示:
MyClass* myClassPtr; //Points to 0x20005c98
其中 myClassPtr->_ptr 的地址應該是 0x200083A8 (0x20005c98 + 0x2710)
但是,當我逐步執行程序集時,這就是我所看到的
0800883a: ldr r6, [r6, #4]
0800883c: add.w r3, r4, #94208 ; 0x17000
08008840: str.w r6, [r3, #3308] ; 0xcec
08008844: add.w r3, r6, #8192 ; 0x2000
08008848: ldr.w r3, [r3, #1532] ; 0x5fc
str.w 是設置我的 myClassPtr 的位置,因此 r6 應該將地址保存到我的 MyClass 實例的開頭。 我可以驗證這是真的(r6 包含 0x20005c98)。
然后 08008844 (add.w) 處的指令應該移動到 unique_ptr 中的適當偏移量,以檢查它是否為 null。但是,0x20005c98 + 0x2000 是 0x20007C98,這在 _ptr 變量開始之前......
我也嘗試過多個版本的編譯器,只是為了確保這不是一個錯誤。
因此,我知道這是我的錯,問題與多個 inheritance 有關,但我就是無法弄清楚問題到底是什么。 對要查找/測試的內容的一些一般性了解將非常有幫助。
順便說一句,我在 MyClass 的構造函數中調用了相同的 function(指針的 bool 轉換運算符)。 它生成了以下程序集:
0802f5a2: add.w r3, r4, #8192 ; 0x2000
0802f5a6: ldr.w r5, [r3, #1812] ; 0x714
在這種情況下,r4 持有 this 指針,但除此之外,它與對 function 的其他調用相同,只是這次偏移量是正確的...
對於遇到此類問題的任何其他人,歸結為由於翻譯單元中的不同 #define 值而違反了“單一定義規則”。
例如,如果 class 定義為:
Foo.hpp:
class Foo
{
private:
std::array<uint8_t, MAX_BUFFER_SIZE> _buffer;
int _foo;
};
文件 A.cpp 在包含 Foo.hpp 時將 MAX_BUFFER_SIZE 定義為 10
文件 B.cpp 在包含 Foo.hpp 時將 MAX_BUFFER_SIZE 定義為 20
因此 _foo 的地址在 A.cpp 和 B.cpp 之間不同,導致匯編代碼不一致。
在我的實際應用程序中,問題的實際原因有點復雜(由於某些包含文件中的拼寫錯誤),但歸結為這一點。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.