Re: [問題] 關於Class指標的觀念

看板C_and_CPP (C/C++)作者 (「雄辯是銀,沉默是金」)時間11年前 (2013/08/28 10:26), 編輯推噓4(4014)
留言18則, 4人參與, 最新討論串8/19 (看更多)
: http://www.parashift.com/c++-faq-lite/cant-cvt-memfnptr-to-voidptr.html : 看來無法將 void* 轉 member function pointer。 : 我用得方法其實是把 member function 當成 non member function, : 再把 this 傳進去。 : 大概像是這樣。 這是 virtual member function 的版本, 基本原理是一樣。 env: g++-4.6.real (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 Ubuntu/Linaro x86 32bit virtual member function: void (A::*p)() = &A::func; 804873f: c7 44 24 14 01 00 00 movl $0x1,0x14(%esp) 8048746: 00 8048747: c7 44 24 18 00 00 00 movl $0x0,0x18(%esp) 804874e: 0 不過我沒搞懂這兩部份是用來幹嘛的? 得請 cppgm 參加人員解惑了。 c 語言應該沒有這麼奇怪的東西吧? #include <iostream> #include <cstdio> using namespace std; struct A { virtual void func() { printf("i: %d\n", i_); } void inc() { ++i_; } A() { i_=10; } private: int i_; }; int main() { void (A::*p)() = &A::func; A a; (a.*p)(); unsigned int vptr_addr = *(unsigned int *)&a; cout << "vptr_addr:" << hex << vptr_addr << endl; unsigned int func_addr = *(unsigned int *)vptr_addr; cout << "func_addr:" << hex << func_addr << endl; a.inc(); (*(void(*)(A*))(func_addr) )(&a); A aa; (*(void(*)(A*))(func_addr) )(&aa); (*(void(*)(A*))(func_addr) )(&a); (*(void(*)(A*))(func_addr) )(&aa); return 0; } 執行結果: i: 10 vptr_addr:8048af8 func_addr:80489b4 i: 11 i: 10 i: 11 i: 10 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 59.125.239.51

08/28 10:37, , 1F
可惜我電腦是 Segmentation fault (流淚)
08/28 10:37, 1F

08/28 11:15, , 2F
還沒玩到那裡不過我猜有一個應該是 vtable 裡的位置
08/28 11:15, 2F
Feis: 自己追比較有趣, 每個人環境都不同, 這是給同好參考用的。 ideone 執行結果: http://ideone.com/KLP0gG

08/28 12:04, , 3F
事實上 64-bit 環境應該都不行. 還有我猜 VC 應該不行.
08/28 12:04, 3F

08/28 12:07, , 4F
這跟我們假定某個實作直接寫組語有異曲同工之妙.
08/28 12:07, 4F

08/28 12:08, , 5F
編譯器的逆向工程~
08/28 12:08, 5F

08/28 12:08, , 6F
不過蠻有趣的. 我去研究一下~
08/28 12:08, 6F

08/28 12:20, , 7F
這種東西不是去找 g++ 的 ABI 文件嗎? 跟當年有人 reverse
08/28 12:20, 7F

08/28 12:21, , 8F
engineer 我 parse 棋譜的功能一樣, 程式碼文件都有幹麼不看
08/28 12:21, 8F

08/28 12:24, , 9F
VC 跑 a.inc(); 的下行會當掉,因為他 this 一定從 ecx 抓
08/28 12:24, 9F

08/28 12:24, , 10F
可是這程式碼是假設 this 從堆疊抓作為前提
08/28 12:24, 10F
可以加上 c call convention 試試看嗎? 也許預設使用了 fastcall convention。 ※ 編輯: descent 來自: 59.125.239.46 (08/28 12:34)

08/28 12:36, , 11F
因為這的 A::func 是成員函式,所以裡面對變數 i 的存取
08/28 12:36, 11F

08/28 12:37, , 12F
是寫死,一定從 this (ecx),成員函式應該不能改呼叫慣例
08/28 12:37, 12F

08/28 12:44, , 13F
http://goo.gl/z3PA5 只有 GCC 的 thiscall 才接近 cdecl
08/28 12:44, 13F

08/28 13:07, , 14F
LPH66: gcc 實作裡那個 0x1 應該就是 vtable 的 offset+1
08/28 13:07, 14F

08/28 13:12, , 15F
另一個應該是存 this 的 offset. 不過不確定. 要查一下
08/28 13:12, 15F

08/28 13:16, , 16F
>descent: VC 的話對非靜態成員函式使用的是 thiscall
08/28 13:16, 16F

08/28 13:17, , 17F
呃, 發覺 purpose 解釋完了 XD
08/28 13:17, 17F

08/28 21:08, , 18F
http://ideone.com/tXALVS (不就是硬幹?)
08/28 21:08, 18F
文章代碼(AID): #1I7L_Kux (C_and_CPP)
討論串 (同標題文章)
文章代碼(AID): #1I7L_Kux (C_and_CPP)