看板 C_and_CPP 關於我們 聯絡資訊
: 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
Feis:可惜我電腦是 Segmentation fault (流淚) 08/28 10:37
LPH66:還沒玩到那裡不過我猜有一個應該是 vtable 裡的位置 08/28 11:15
Feis: 自己追比較有趣, 每個人環境都不同, 這是給同好參考用的。 ideone 執行結果: http://ideone.com/KLP0gG
Feis:事實上 64-bit 環境應該都不行. 還有我猜 VC 應該不行. 08/28 12:04
Feis:這跟我們假定某個實作直接寫組語有異曲同工之妙. 08/28 12:07
Feis:編譯器的逆向工程~ 08/28 12:08
Feis:不過蠻有趣的. 我去研究一下~ 08/28 12:08
scwg:這種東西不是去找 g++ 的 ABI 文件嗎? 跟當年有人 reverse 08/28 12:20
scwg:engineer 我 parse 棋譜的功能一樣, 程式碼文件都有幹麼不看 08/28 12:21
ref: http://www.agner.org/optimize/calling_conventions.pdf http://refspecs.linux-foundation.org/cxxabi-1.83.html (g++ 好像是參考這份實作)
purpose:VC 跑 a.inc(); 的下行會當掉,因為他 this 一定從 ecx 抓 08/28 12:24
purpose:可是這程式碼是假設 this 從堆疊抓作為前提 08/28 12:24
可以加上 c call convention 試試看嗎? 也許預設使用了 fastcall convention。 ※ 編輯: descent 來自: 59.125.239.46 (08/28 12:34)
purpose:因為這的 A::func 是成員函式,所以裡面對變數 i 的存取 08/28 12:36
purpose:是寫死,一定從 this (ecx),成員函式應該不能改呼叫慣例 08/28 12:37
purpose:http://goo.gl/z3PA5 只有 GCC 的 thiscall 才接近 cdecl 08/28 12:44
Feis:LPH66: gcc 實作裡那個 0x1 應該就是 vtable 的 offset+1 08/28 13:07
Feis:另一個應該是存 this 的 offset. 不過不確定. 要查一下 08/28 13:12
LPH66:>descent: VC 的話對非靜態成員函式使用的是 thiscall 08/28 13:16
LPH66:呃, 發覺 purpose 解釋完了 XD 08/28 13:17
Feis:http://ideone.com/tXALVS (不就是硬幹?) 08/28 21:08