Testing this feature was designed to test the bind in boost
Boost::bind (&a::sum), &a, _1, _2)
The above code is my boost bind and multi-threaded this blog inside a line of code. I just want to know how boost is done. Call a member function of a class. In fact, member functions and global functions are nothing more than a this pointer parameter. It can also be called if it is passed in. But it's not that simple. See the boost source code is too long to say. I don't know how to read.
And then you write your own code to test a bit. Also used in the assembly.
Code reference http://www.cppblog.com/woaidongmao/archive/2010/03/11/109444.aspx
There are two methods of invocation, one is to put the this pointer into the ECX register, one is to press the this pointer as the last parameter into the stack
My computer environment is Ubuntu 64-bit, from the generated assembly, not press into the ECX, but press into the RDI. The registers that start with R are all 64-bit. Then I would like to simulate the invocation method of the member function, manually pressing into a this pointer, the first attempt to code as follows. Run the report segment fault. View assembly code Discovery. EDI is used after parameters are passed. This is caused by the manual pressing of this is destroyed ....
#include <cstdio>using namespace Std;class tt{public:/* void foo (int x) {printf ("arg:x=%d\n" , x); }*/void foo (int x, char c = ten, char * s = "Hello") {printf ("_m_s=%d%d%c%s\n", _m_s, X, C, s); } int _m_s;}; typedef void (TT::* funptr) (int, char, char*), typedef void (*GLOBALPTR) (int, char, char*);template< class ToType, CLA SS Fromtype>void Getmemberfuncaddr (totype& addr, fromtype from) {union{fromtype _f; ToType _t; } ut; Use Union to bypass C + + type checking ut._f = from; addr = ut._t;} Long Long This;int main () {TT T; t._m_s = 123; char *ptrc = "Hello"; Funptr ptr = &tt::foo; (T.*PTR) (Ten, ' a ', ptrc); printf ("%x\n", PTR); Long long p; p = (int) (&TT::FOO); Type mismatch cannot force type conversion getmemberfuncaddr (P, &tt::foo); printf ("%x\n", p); Globalptr P1 = (globalptr) p;//P1 (10000, ' C ', PTRC); This = (long long) &t; __asm__ ("movq this,%rdi \ n" ); P1 (10000, ' C ', PTRC); return 0;}
g++-o1-s test_thisptr.cpp generate assembly code
. File "Test_thisptr.cpp". section.rodata.str1.1, "AMS", @progbits, 1.lc0:.string "_m_s=%d%d%c%s\n". section.text._ ZN2TT3FOOEICPC, "AxG", @progbits, _zn2tt3fooeicpc,comdat.align 2.WEAK_ZN2TT3FOOEICPC.TYPE_ZN2TT3FOOEICPC, @function _ZN2TT3FOOEICPC:. Lfb30:.cfi_startprocsubq$8,%rsp.cfi_def_cfa_offset 16movq%rcx,%r9movsbl%dl,%r8dmovl%esi,%ECXMOVL (%rdi),%EDXMOVL $. LC0,%esimovl$1,%edimovl$0,%eaxcall__printf_chkaddq$8,%rsp.cfi_def_cfa_offset 8ret.cfi_endproc. LFE30:.SIZE_ZN2TT3FOOEICPC,.-_zn2tt3fooeicpc.section.rodata.str1.1.lc1:.string "Hello". Lc2:.string "%x\n". Text.globlmain.typemain, @functionmain:. lfb32:.cfi_startprocsubq$24,%rsp.cfi_def_cfa_offset 32movl$123, (%RSP)//The following 5 lines show the assembly code for normal points with member functions (T.*PTR) (' A ', PTRC) movl$. LC1,%ecxmovl$97,%edxmovl$10,%ESIMOVQ%RSP,%RDICALL_ZN2TT3FOOEICPCMOVL$_ZN2TT3FOOEICPC,%edxmovl$0,%ecxmovl$. LC2,%esimovl$1,%edimovl$0,%EAXCALL__PRINTF_CHKMOVL$_ZN2TT3FOOEICPC,%edxmovl$. LC2,%esimovl$1,%edimovl$0,%EAXCALL__PRINTF_CHKMOVQ%RSP, this (%rip) #APP # "Test_ThisPtr.cpp "1movq This,%rdi# 0" "2#no_app//4 lines below shows P1 (10000, ' C ', PTRC); Call code//Less movq%rsp,%rdi command, that is, press the this pointer movl$. LC1,%edxmovl$99,%esimovl$10000,%edicall_zn2tt3fooeicpcmovl$0,%eaxaddq$24,%rsp.cfi_def_cfa_offset 8ret.cfi_ Endproc. Lfe32:.sizemain,.-main.globlthis.bss.align 8.typeThis, @object. Sizethis, 8this:.zero8.ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4 ". Section.note.gnu-stack," ", @progbits
Modify the code as follows: Remove the parameters of the function to ensure that EDI is not used. And then the most important point. Turn the type of this to unsigned long long. Otherwise the assembly code will sign the extension. Cause still reported segment fault.
#include <cstdio>using namespace Std;class tt{public:/* void foo (int x) {printf ("arg:x=%d\n" , x); }*/void foo () {printf ("_m_s=%d%d\n", _m_s); } int _m_s;}; typedef void (TT::* funptr) (), typedef void (*GLOBALPTR) ();template< class ToType, class Fromtype>void Getmemberfuncaddr (totype& addr, fromtype from) {union{fromtype _f; ToType _t; } ut; Ut._f = from; addr = ut._t;} Unsigned long long this;int main () {TT T; t._m_s = 123; char *ptrc = "Hello"; Funptr ptr = &tt::foo; (T.*PTR) (); printf ("%x\n", PTR); Long long p; p = (int) (&TT::FOO); Type mismatch cannot force type conversion getmemberfuncaddr (P, &tt::foo); printf ("%x\n", p); Globalptr P1 = (globalptr) p;//P1 (10000, ' C ', PTRC); This = (long long) &t; __asm__ ("movq this,%rdi \ n"); P1 (); return 0;
Assembly Code:
<pre name= "code" class= "CPP" >.file "Test_thisptr.cpp". section.rodata.str1.1, "AMS", @progbits, 1.lc0:.string "_ m_s=%d%d\n ". Section.text._zn2tt3fooev," AxG ", @progbits, _zn2tt3fooev,comdat.align 2.weak_zn2tt3fooev.type_ Zn2tt3fooev, @function_ZN2tt3fooEv:. Lfb30:.cfi_startprocsubq$8,%rsp.cfi_def_cfa_offset 16movl (%rdi),%edxmovl$. LC0,%esimovl$1,%edimovl$0,%eaxcall__printf_chkaddq$8,%rsp.cfi_def_cfa_offset 8ret.cfi_endproc. Lfe30:.size_zn2tt3fooev,.-_zn2tt3fooev.section.rodata.str1.1.lc1:.string "%x\n". Text.globlmain.typemain, @ Functionmain:. lfb32:.cfi_startprocsubq$24,%rsp.cfi_def_cfa_offset 32movl$123, (%RSP) MOVQ%RSP,%rdicall_zn2tt3fooevmovl$_ Zn2tt3fooev,%edxmovl$0,%ecxmovl$. LC1,%esimovl$1,%edimovl$0,%eaxcall__printf_chkmovl$_zn2tt3fooev,%edxmovl$. LC1,%esimovl$1,%edimovl$0,%EAXCALL__PRINTF_CHKMOVQ%RSP, this (%rip) #APP # "Test_thisptr.cpp" 1movq This,%rdi# 0 "" No_appcall_zn2tt3fooevmovl$0,%eaxaddq$24,%rsp.cfi_def_cfa_offset 8ret.cfi_endproc. Lfe32:.sizemain,.-main.gloBlThis.bss.align 8.typeThis, @object. Sizethis, 8this:.zero8.ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4". Section.note.gnu-stack, "", @progbits
How C + + passes the this pointer to member functions called member functions like global functions