2012-08-09 75 views
25

我在調試GDB中的一些C++代碼,發現有些調用正在使用所謂的「合成指針」。谷歌搜索沒有產生任何有意義的結果。在這裏搜索,大多數題目中「合成」的問題都涉及到一些Java特性(即使它們暗示「合成」在這種情況下可能意味着「編譯器人工產生的東西」)。什麼是合成指針?

例如,看這回溯,從一個操作,在MyClass構造進行了,在一個類的成員稱爲m(此代碼已被編譯-O2):

#0 MyClass (arg=..., this=<synthetic pointer>) at somefile.h:144 
144  m->lock(); 
gdb$ print this 
$1 = (MyClass * const) <synthetic pointer> 
gdb$ print *this 
$2 = <optimized out> 

上述棧跟蹤明確指出this是一個指向已經優化過的對象的指針,但是如何調用一個方法(即它的構造函數)呢?我的猜測是,即使在代碼中主動使用了封閉對象(m),一些優化讓編譯器可以確定封閉對象(this)並非真的必要。由於無法優化的方法調用m->lock()必須放在某處,因此編譯器會創建一個位於內存中的「假」(合成?)對象,僅用於包裝m

我沒有強大的編譯器經驗,所以我不知道這個結論是否真的有意義。請問有人可以解釋一下嗎?

謝謝。

回答

12

編譯器可以確定this是否實際被解除引用(即使用特定的CPU詳細信息,而不是一般的C++規則)。如果某個方法實際上沒有取消引用this,則不需要有可用的財務表示。

在評論中,jww提到了另一個案例。一個singleton只有一個副本,所以一個聰明的編譯器可以把它的成員當作全局變量。這意味着singleton->foo的地址只是常數&singleton + offset(foo)。作爲這種優化的結果,單例方法不需要實際取消引用this以獲得對單例成員的訪問,因此它可以再次被優化。

+0

是的,我的MyClass對象是構造的,從未被引用過,並在一段時間後被銷燬;唯一重要的操作是構造函數/析構函數的副作用(對於記錄,它是範圍鎖的自定義實現)。所以這一定是這樣。謝謝。 – 2012-08-09 18:34:58

+2

這是一個合成指針實際上是什麼(當「這」被優化了)?我覺得這個答案可以解釋爲一個附註,即如果從未引用過某個對象可以被優化出來,但並不是說「合成指針」就是「優化」出來的情況。我在堆棧跟蹤中看到了合成指針,我不知道如何解釋它不是常規的消息。 – 2013-09-18 16:11:04

+2

@JoeyCarson:這一切都有點哲理。形式上,對象既可以存在也可以不存在。優化器運行後,對象可能部分存在,達到可觀察行爲程序所需的程度。調試器要僞造真實對象,這不是科學。 – MSalters 2013-09-18 19:55:20