2016-06-23 18 views
2

C++語言不允許您在分配引用後更改引用。不過,我有一個調試需求/願望來更改引用以幫助調試某些內容。是否有一種基本上用新指針覆蓋參考實現的方法?一旦你得到了一個你想改變的對象的地址,你可以將它轉換爲任何你想要的並覆蓋它。我無法弄清楚如何獲得底層參考實例的內存地址;使用&來取消引用不會引用引用的地址,而是引用引用的對象的地址。如何更改C++引用(通過任何必要的方式)

我意識到這顯然會引發未定義的行爲,這只是一個實驗。第三方庫有一個全局引用的bug,在代碼執行之前沒有被構建,我想看看我是否可以通過自己設置引用來修復它。在這一點上,它成爲一個挑戰,看它是否有可能。我知道你可以用匯編語言來做這件事,如果你可以直接引用符號表。

我想像這樣。這些是全球範圍的變量。

Apple a; 
Apple& ref = a; 

後來我想ref指一個新的對象實例b並獨自離開a

Apple b; 

ref = b; // that doesn't work. that justs sets a=b. 

&ref = &b; // that doesn't work. the compiler complains. 

uint64_t addr = find_symbol_by_any_means_necessary(ref); 
*(Apple**)addr = &b; // this should work if I could get addr 

請不要提醒我這是個壞主意。我知道這是一個壞主意。將其視爲挑戰。這僅用於調試,以便快速測試假設。我想了解一些關於C++二進制代碼內部的知識。 (請告訴我,如果系統頁面保護是不可能的,那麼如果引用被放置在神聖的地方,我可能會遇到seg故障)。

(系統是CentOS 7,編譯器是英特爾,雖然我可以使用gcc進行這個實驗)。

+0

呃,你確定這不起作用嗎?試試這個代碼:'Apple a; Apple &a_ref; Apple b; a_ref = b;'用'Apple'類來監視它的拷貝構造,移動賦值等。我相當肯定你會發現'a_ref'現在指向'b';它不僅僅是複製數據。如果你做了'a = b',但你不是。 –

+0

@QPaysTaxes,在引用上使用賦值運算符分配給被引用對象。 – chris

+0

@QPaysTaxes:您提供的代碼示例不會編譯。 'Apple &a_ref;'無效。以下代碼:'Apple a; Apple&a_ref = a; a_ref = b;'等同於Apple a; a = b;' –

回答

4

我不認爲有一種方法可以重新引導獨立引用變量引用的對象。

如果在struct中作爲成員變量包含引用,則可以輕鬆地將該對象更改爲引用變量引用。這很可能是UB,但它適用於我當前版本的g ++,g ++ 4.8.4。

下面是一個演示方法的示例程序。

#include <iostream> 
#include <cstring> 

struct Foo 
{ 
    int& ref; 
}; 

int main() 
{ 
    int a = 10; 
    int b = 20; 

    Foo foo = {a}; // foo.ref is a reference to a 
    std::cout << foo.ref << std::endl; 

    // Use memcpy to change what foo.ref references 
    int* bPtr = &b; 
    std::memcpy(&foo, &bPtr, sizeof(bPtr)); 

    // Now, foo.ref is a reference to b 
    std::cout << foo.ref << std::endl; 

    // Changing foo.ref changes b 
    foo.ref = 30; 
    std::cout << b << std::endl; 
} 

輸出:

10 
20 
30 
+1

+1我不能改變參考,否則代碼會破壞......但你給了我一個主意。在引用前放置犧牲變量*,並假定犧牲變量和引用順序放置在內存中。獲取犧牲變量的地址並添加幾個字節的偏移量以獲取參考文獻... –

0

它一般是不可能的,因爲這樣一個事實:引用不是可復位讓很多優化。例如,引用通常作爲指針實現,但編譯器也可能會注意到您經常使用固定的偏移量。所以除了存儲指針之外,編譯器可以決定存儲指針加偏移量。它甚至可能決定只存儲指針加偏移量。

另一個優化是將參考地址存儲在CPU寄存器中。由於它不能改變,編譯器不需要重新加載它。

因此,您可以在彙編中更改它的陳述頗具誤導性。你不知道在優化之後參考的表示是什麼,並且這種優化將依賴於情境。

相關問題