C++憤恨者劄記3——函數呼叫慣例

來源:互聯網
上載者:User

C++憤恨者劄記3——函數呼叫慣例

    函數呼叫慣例指的是,參數壓棧順序及彈棧位置的約定。這個約定在函式宣告時指定,如:

 void __stdcall Fn(int arg1,  int arg2);

    其中__stdcall就是呼叫慣例,表示參數從右至左入棧,而函數自己負責參數彈棧工作。

    還有一種常用約定為__cdecl,表示參數從右至左入棧,而函數調用者負責參數彈棧工作。

    如果沒有指定呼叫慣例,編譯器會使用預設約定。VS中預設約定可以在工程屬性中設定:


    VC++中,一般函數使用__cdecl約定,但類成員函數,包括建構函式,使用__stdcall約定(我不知道為什麼),從它們的反組譯碼代碼中可以看出。

源碼:

class Node{public:Node(){}void Fn( int a, int b ){}};void Fn(int a, int b){}void main(){Node n;n.Fn(1, 2);Fn( 1, 2);}

   main與Fn反組譯碼代碼如下:

-------------------------------------------------------------------------------------------------------------------

   函數呼叫慣例在彙編中,區別是巨大的,而在進階語言裡卻很少進入視野。下面給出一個因約定不一致導致程式崩潰的例子。程式要在debug版本下編譯,或release版下把/Od打上,禁止最佳化,否則可能看不到程式崩潰。

typedef void (__cdecl *CDeclType)(void*);void __stdcall Fn(void* p){}void MyCallBack( CDeclType pFn ){pFn(0);/*pFn的參數將會被兩次彈棧,破壞棧平衡MyCallBack將找不到返回地址*/}void main(){MyCallBack( (CDeclType)Fn );}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.