簡體   English   中英

使用多個時指針偏移不正確 inheritance

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM