कोड इस प्रकार हैं के लिए आभासी समारोह तालिका में ऑफसेट (सी ++ 11 कोड जी के साथ ++ संकलित - उबंटू 16.04 पर 5.4):आभासी आधार आभासी विरासत
#include <iostream>
using namespace std;
class Base
{
public:
virtual void show()
{
cout << "Base" << endl;
}
virtual void func()
{
cout << "func in Base" << endl;
}
protected:
int base = 15;
};
class A: public virtual Base
{
public:
void show() override
{
cout << this << endl;
cout << 'A' << endl;
}
void func() override
{
cout << this << endl;
cout << "func in A" << endl;
}
protected:
int a = 31;
};
int main(int argc, const char *argv[])
{
A obj_a;
return 0;
}
मैं स्मृति लेआउट की जाँच करने के GDB उपयोग करने का प्रयास वस्तु "obj_a" के (सबसे पहले, मैं "पर सेट प्रिंट वस्तु", "प्रिंट सुंदर पर सेट", "पर प्रिंट vtbl सेट" सेट "सेट प्रिंट एएसएम-demangle पर" GDB में):
(gdb) p sizeof(obj_a)
$1 = 32
(gdb) x/8aw &obj_a
0x7fffffffe320: 0x400d20 <vtable for A+24> 0x0 0x1f 0x0
0x7fffffffe330: 0x400d50 <vtable for A+72> 0x0 0xf 0x0
हम जानते हैं कि obj_a और उसके वर्चुअल बेस सबोबजेक्ट की शुरुआत के बीच ऑफसेट 16 बी (वर्चुअल बेस ऑफ़सेट) है। और फिर मैं जाँच एक की आभासी समारोह तालिका द्वारा 0x400d08 (0x400d20 - 24) कहा:
(gdb) x/14ag 0x400d08
0x400d08 <vtable for A>: 0x10 0x0
0x400d18 <vtable for A+16>: 0x400d90 <typeinfo for A> 0x400b46 <A::show()>
0x400d28 <vtable for A+32>: 0x400b98 <A::func()> 0xfffffffffffffff0
0x400d38 <vtable for A+48>: 0xfffffffffffffff0 0xfffffffffffffff0
0x400d48 <vtable for A+64>: 0x400d90 <typeinfo for A> 0x400b8f <virtual thunk to A::show()>
0x400d58 <vtable for A+80>: 0x400be1 <virtual thunk to A::func()> 0x400d20 <vtable for A+24>
0x400d68 <VTT for A+8>: 0x400d50 <vtable for A+72> 0x0
हम देख सकते हैं, वहाँ दो "को XXX में आभासी thunk", अर्थात् "0x400b8f" और "0x400be1" कर रहे हैं। मैं इन दो पतों में सहकर्मी हूं।
(gdb) x/3i 0x400b8f
0x400b8f <virtual thunk to A::show()>: mov (%rdi),%r10
0x400b92 <virtual thunk to A::show()+3>: add -0x18(%r10),%rdi
0x400b96 <virtual thunk to A::show()+7>: jmp 0x400b46 <A::show()>
(gdb) x/3i 0x400be1
0x400be1 <virtual thunk to A::func()>: mov (%rdi),%r10
0x400be4 <virtual thunk to A::func()+3>: add -0x20(%r10),%rdi
0x400be8 <virtual thunk to A::func()+7>: jmp 0x400b98 <A::func()>
मेरे प्रश्न हैं: क्या ", -0x18 (% R10) जोड़ने% RDI" और "-0x20 (% R10),% RDI जोड़ें" वास्तव में क्या मतलब है? -24 (-0x18) और -32 (-0x20) क्यों हैं? (मुझे लगता है कि वे सभी -16 होना चाहिए)
मुझे लगता है कि आप कार्यों के कार्यान्वयन – Rerito
हाय रेरिटो के लिए एएसएम देखकर जवाब प्राप्त करेंगे, आपके उत्तर के लिए धन्यवाद। मैंने दो आभासी कार्यों के कार्यान्वयन के लिए एएसएम कोड की जांच की, मेरे पास कोई जवाब नहीं था। असल में, मैं वास्तव में जानना चाहता हूं कि फ़ंक्शन निष्पादित करने से पहले इस पॉइंटर को कैसे बदला जाए। – Jason
ओह, मुझे यह पता है। यहां इसे ऑफसेट को अप्रत्यक्ष तरीके से प्राप्त करने की आवश्यकता है। "vtbl - 0x18" आभासी फ़ंक्शन तालिका में ऑफ़सेट मान इंगित करता है। और फिर ऑफसेट जोड़कर "यह" को सही कर रहा है। – Jason