多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國(guó)內(nèi)最全I(xiàn)T社區(qū)平臺(tái) 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當(dāng)前位置:首頁(yè) > php開(kāi)源 > php教程 > 《coredump問(wèn)題原理探究》Linux x86版6.4節(jié)虛函數(shù)

《coredump問(wèn)題原理探究》Linux x86版6.4節(jié)虛函數(shù)

來(lái)源:程序員人生   發(fā)布時(shí)間:2015-03-02 08:42:22 閱讀次數(shù):3171次

在上1節(jié)已探究了類的成員變量的排列,現(xiàn)在看1下虛函數(shù)表和成員變量的排列及虛函數(shù)之間的排列.

先看1個(gè)例子:

1 #include <stdio.h> 2 class xuzhina_dump_c06_s3 3 { 4 private: 5 int m_a; 6 public: 7 xuzhina_dump_c06_s3() { m_a = 0; } 8 virtual void inc() { m_a++; } 9 virtual void dec() { m_a--; } 10 virtual void print() 11 { 12 printf( "%d ", m_a ); 13 } 14 }; 15 16 int main() 17 { 18 xuzhina_dump_c06_s3* test = new xuzhina_dump_c06_s3; 19 if ( test != NULL ) 20 { 21 test->inc(); 22 test->inc(); 23 test->print(); 24 } 25 return 0; 26 }

匯編代碼:

(gdb) disassemble main Dump of assembler code for function main: 0x08048560 <+0>: push %ebp 0x08048561 <+1>: mov %esp,%ebp 0x08048563 <+3>: push %ebx 0x08048564 <+4>: and $0xfffffff0,%esp 0x08048567 <+7>: sub $0x20,%esp 0x0804856a <+10>: movl $0x8,(%esp) 0x08048571 <+17>: call 0x8048450 <_Znwj@plt> 0x08048576 <+22>: mov %eax,%ebx 0x08048578 <+24>: mov %ebx,(%esp) 0x0804857b <+27>: call 0x80485cc <_ZN19xuzhina_dump_c06_s3C2Ev> 0x08048580 <+32>: mov %ebx,0x1c(%esp) 0x08048584 <+36>: cmpl $0x0,0x1c(%esp) 0x08048589 <+41>: je 0x80485c1 <main+97> 0x0804858b <+43>: mov 0x1c(%esp),%eax 0x0804858f <+47>: mov (%eax),%eax 0x08048591 <+49>: mov (%eax),%eax 0x08048593 <+51>: mov 0x1c(%esp),%edx 0x08048597 <+55>: mov %edx,(%esp) 0x0804859a <+58>: call *%eax 0x0804859c <+60>: mov 0x1c(%esp),%eax 0x080485a0 <+64>: mov (%eax),%eax 0x080485a2 <+66>: mov (%eax),%eax 0x080485a4 <+68>: mov 0x1c(%esp),%edx 0x080485a8 <+72>: mov %edx,(%esp) 0x080485ab <+75>: call *%eax 0x080485ad <+77>: mov 0x1c(%esp),%eax 0x080485b1 <+81>: mov (%eax),%eax 0x080485b3 <+83>: add $0x8,%eax 0x080485b6 <+86>: mov (%eax),%eax 0x080485b8 <+88>: mov 0x1c(%esp),%edx 0x080485bc <+92>: mov %edx,(%esp) 0x080485bf <+95>: call *%eax 0x080485c1 <+97>: mov $0x0,%eax 0x080485c6 <+102>: mov -0x4(%ebp),%ebx 0x080485c9 <+105>: leave 0x080485ca <+106>: ret End of assembler dump.

由上面代碼可知,履行完了構(gòu)造函數(shù),test的m_a的值,會(huì)變成0。且由上面匯編可以看到this指針在調(diào)用構(gòu)造函數(shù)前后,是放在ebx寄存器。

在0x08048578,0x08048580都打斷點(diǎn),看1下this指針?biāo)赶虻牡刂肥欠袷沁@樣的結(jié)果。

(gdb) tbreak *0x08048578 Temporary breakpoint 1 at 0x8048578 (gdb) tbreak *0x08048580 Temporary breakpoint 2 at 0x8048580 (gdb) r Starting program: /home/buckxu/work/6/3/xuzhina_dump_c6_s3 Temporary breakpoint 1, 0x08048578 in main () (gdb) x /4x $ebx 0x804a008: 0x00000000 0x00000000 0x00000000 0x00020ff1 (gdb) c Continuing. Temporary breakpoint 2, 0x08048580 in main () (gdb) x /4x $ebx 0x804a008: 0x080486d0 0x00000000 0x00000000 0x00020ff1

非常奇怪,依照上1節(jié)的內(nèi)容,地址0x804a008應(yīng)當(dāng)寄存m_a,會(huì)初始化為0.究竟類xuzhina_dump_c06_s3的構(gòu)造函數(shù)做了甚么事情?而0x080486d0是甚么東西來(lái)的?

看1下類xuzhina_dump_c06_s3的構(gòu)造函數(shù):

(gdb) disassemble _ZN19xuzhina_dump_c06_s3C2Ev Dump of assembler code for function _ZN19xuzhina_dump_c06_s3C2Ev: 0x080485cc <+0>: push %ebp 0x080485cd <+1>: mov %esp,%ebp 0x080485cf <+3>: mov 0x8(%ebp),%eax 0x080485d2 <+6>: movl $0x80486d0,(%eax) 0x080485d8 <+12>: mov 0x8(%ebp),%eax 0x080485db <+15>: movl $0x0,0x4(%eax) 0x080485e2 <+22>: pop %ebp 0x080485e3 <+23>: ret End of assembler dump.

由構(gòu)造函數(shù)的匯編可知,0x80486d0這個(gè)值是在構(gòu)造函數(shù)設(shè)置,但還不清楚是甚么東西。而

0x080485d8 <+12>: mov 0x8(%ebp),%eax 0x080485db <+15>: movl $0x0,0x4(%eax)

卻恰好對(duì)應(yīng)了

7 xuzhina_dump_c06_s3() { m_a = 0; }

也就是說(shuō),類xuzhina_dump_c06_s3的第1個(gè)成員變量m_a放在偏移this指針的地方,那末0x80486d0是甚么東西,占了m_a的位置呢?

重新看1下main函數(shù)的匯編:

(gdb) disassemble main Dump of assembler code for function main: 0x08048560 <+0>: push %ebp 0x08048561 <+1>: mov %esp,%ebp 0x08048563 <+3>: push %ebx 0x08048564 <+4>: and $0xfffffff0,%esp 0x08048567 <+7>: sub $0x20,%esp 0x0804856a <+10>: movl $0x8,(%esp) 0x08048571 <+17>: call 0x8048450 <_Znwj@plt> 0x08048576 <+22>: mov %eax,%ebx 0x08048578 <+24>: mov %ebx,(%esp) 0x0804857b <+27>: call 0x80485cc <_ZN19xuzhina_dump_c06_s3C2Ev> => 0x08048580 <+32>: mov %ebx,0x1c(%esp) 0x08048584 <+36>: cmpl $0x0,0x1c(%esp) 0x08048589 <+41>: je 0x80485c1 <main+97> 0x0804858b <+43>: mov 0x1c(%esp),%eax 0x0804858f <+47>: mov (%eax),%eax 0x08048591 <+49>: mov (%eax),%eax 0x08048593 <+51>: mov 0x1c(%esp),%edx 0x08048597 <+55>: mov %edx,(%esp) 0x0804859a <+58>: call *%eax 0x0804859c <+60>: mov 0x1c(%esp),%eax 0x080485a0 <+64>: mov (%eax),%eax 0x080485a2 <+66>: mov (%eax),%eax 0x080485a4 <+68>: mov 0x1c(%esp),%edx 0x080485a8 <+72>: mov %edx,(%esp) 0x080485ab <+75>: call *%eax 0x080485ad <+77>: mov 0x1c(%esp),%eax 0x080485b1 <+81>: mov (%eax),%eax 0x080485b3 <+83>: add $0x8,%eax 0x080485b6 <+86>: mov (%eax),%eax 0x080485b8 <+88>: mov 0x1c(%esp),%edx 0x080485bc <+92>: mov %edx,(%esp) 0x080485bf <+95>: call *%eax 0x080485c1 <+97>: mov $0x0,%eax 0x080485c6 <+102>: mov -0x4(%ebp),%ebx 0x080485c9 <+105>: leave 0x080485ca <+106>: ret End of assembler dump.

0x0804857b <+27>: call 0x80485cc <_ZN19xuzhina_dump_c06_s3C2Ev> 0x08048580 <+32>: mov %ebx,0x1c(%esp)

可知,esp+0x1c用來(lái)寄存this指針。

再看1下這幾段指令:

0x0804858b <+43>: mov 0x1c(%esp),%eax 0x0804858f <+47>: mov (%eax),%eax 0x08048591 <+49>: mov (%eax),%eax 0x08048593 <+51>: mov 0x1c(%esp),%edx 0x08048597 <+55>: mov %edx,(%esp) 0x0804859a <+58>: call *%eax 0x0804859c <+60>: mov 0x1c(%esp),%eax 0x080485a0 <+64>: mov (%eax),%eax 0x080485a2 <+66>: mov (%eax),%eax 0x080485a4 <+68>: mov 0x1c(%esp),%edx 0x080485a8 <+72>: mov %edx,(%esp) 0x080485ab <+75>: call *%eax 0x080485ad <+77>: mov 0x1c(%esp),%eax 0x080485b1 <+81>: mov (%eax),%eax 0x080485b3 <+83>: add $0x8,%eax 0x080485b6 <+86>: mov (%eax),%eax 0x080485b8 <+88>: mov 0x1c(%esp),%edx 0x080485bc <+92>: mov %edx,(%esp) 0x080485bf <+95>: call *%eax

由因而順序結(jié)構(gòu),可知,這3段指令恰好對(duì)應(yīng)

21 test->inc(); 22 test->inc(); 23 test->print();

分析1下第3段匯編:

0x080485ad <+77>: mov 0x1c(%esp),%eax 0x080485b1 <+81>: mov (%eax),%eax 0x080485b3 <+83>: add $0x8,%eax 0x080485b6 <+86>: mov (%eax),%eax 0x080485b8 <+88>: mov 0x1c(%esp),%edx 0x080485bc <+92>: mov %edx,(%esp) 0x080485bf <+95>: call *%eax

可見(jiàn)eax正好是放著print這個(gè)虛函數(shù)的指針。而這個(gè)指針終究是由esp+0x1c來(lái)獲得。由

0x080485ad <+77>: mov 0x1c(%esp),%eax 0x080485b1 <+81>: mov (%eax),%eax

可知,正好是從this指針的第1個(gè)成員取出來(lái)的,也就是說(shuō),這個(gè)成員是虛函數(shù)表指針。根據(jù)上面的分析,可知這個(gè)虛函數(shù)表指針的值是0x80486d0。來(lái)驗(yàn)證1下,它是否是虛函數(shù)表指針。

(gdb) x /4x 0x80486d0 0x80486d0 <_ZTV19xuzhina_dump_c06_s3+8>: 0x080485e4 0x080485f8 0x0804860c 0x75783931 (gdb) shell c++filt _ZTV19xuzhina_dump_c06_s3 vtable for xuzhina_dump_c06_s3 (gdb) info symbol 0x080485e4 xuzhina_dump_c06_s3::inc() in section .text of /home/buckxu/work/6/3/xuzhina_dump_c6_s3 (gdb) info symbol 0x080485f8 xuzhina_dump_c06_s3::dec() in section .text of /home/buckxu/work/6/3/xuzhina_dump_c6_s3 (gdb) info symbol 0x0804860c xuzhina_dump_c06_s3::print() in section .text of /home/buckxu/work/6/3/xuzhina_dump_c6_s3

可見(jiàn),0x80486d0所指向正是虛函數(shù)表,且里面的表項(xiàng)順序正好和虛函數(shù)的聲明順序1樣。

 

由上面分析,test所指向的對(duì)象的內(nèi)存布局以下圖:


生活不易,碼農(nóng)辛苦
如果您覺(jué)得本網(wǎng)站對(duì)您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關(guān)閉
程序員人生
主站蜘蛛池模板: 九色91精品国产网站 | 三级黄在线观看 | 综合图片小说 | 日本一级淫片aaaaaa | 91av综合| 中文字幕观看 | 成人自拍网| 伊人高清 | 欧美国产日韩另类 | 国产欧美日韩中文久久 | 性欧美性free | 国产精品成人亚洲 | 色最快国产 | 羞羞视频日本动漫免费网站 | 爱爱欧美在线观看视频 | 免费v片在线观看 | 午夜视频在线观看免费视频 | 国产不卡一区二区三区免费视 | 日本一视频一区视频二区 | 一级毛片在线免费观看 | 国产欧美在线一区二区三区 | 性xxxx视频播放免费 | 91精品国产91热久久p | 午夜美女写真福利写视频 | 亚洲制服一区 | 午夜影院免费体验 | 亚洲欧美一区二区三区综合 | 日韩视频在线观看一区 | 国产不卡一区二区三区免费视 | 爱爱精品视频 | 羞羞网站免费观看 | 欧美性大交 | 亚洲爽爽 | 女男羞羞视频网站免费 | 免费网站在线观看高清版 | 嫩草影院精品视频在线观看 | 日本三级理论片 | 欧美亚洲另类小说 | 91嫩草国产在线观看免费 | 日韩欧美一区二区精品久久 | 成人做视频免费 |