青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

posts - 297,  comments - 15,  trackbacks - 0

(VC編譯器下)

 

1. CALLBACKWINAPIAFXAPI到底是什么?它們分別在什么地方 被定義的?

在頭文件windef.h中,CALLBACK, WINAPI, APIENTRY

……

#define CALLBACK  __stdcall

#define WINAPI         __stdcall

#define WINAPIV       __cdecl

#define APIENTRY    WINAPI

……

 

在頭文件AFXVER_.H中,AFXAPI的定義如下:

    ……

   // AFXAPI is used on global public functions

#ifndef AFXAPI

        #define AFXAPI __stdcall

#endif

    ……

 

2. __stdcall__cdecl有什么作用?他們的區別是什么?

a. __stdcall是新標準C/C++函數的調用方法。從底層上說,使用這種調用方法參數的進棧順序和 標準C調用(__cdecl方法)是一樣的,都

  是從右到左,但是__stdcall采用自動清棧的方式,而__cdecl是手工清棧。

b. windows規定,凡事由它來負責調用的函數必須定義為_stdcall類型,比如回調函數、WinMain函數等。

c. 如果沒有顯試聲明的話,函數的調用方法默認是__cdecl。

 

3. 調用約定種類

   一共有5中函數調用約定(calling convention),它決定一下內 容:

   1) 函數參數的壓棧順序

   2) 由調用者還是被調用者把參數彈出棧

   3) 產生函數修飾名的方法

 

__stdcall調用約定:

函數的參數自右向左通過棧傳遞,被調用的函數在返回前清理傳送參數的內存棧,

 

__cdecl調用約定:

是C和C++程序的缺省調用方式。每一個調用它的函數都包含清空堆棧的代碼, 所以產生的可執行文件大小會比調用__stdcall函數的大。函數采用從右到左的壓棧方式。注意:對于可變參數的成員函數,始終使用__cdecl的轉換方式。

 

__fastcall調用約定:

它是通過寄存器來傳送參數的(實際上,它用ECX和EDX傳送前兩個雙字(DWORD)或更小的參數,剩下的參數仍舊自右向左壓棧傳送,被調用的函數在 返回前清理傳送參數的內存棧)。

 

thiscall調用約定:

僅僅應用于"C++"成 員函數。this指 針存放于CX寄存 器,參數從右到左壓。thiscall不是關鍵詞,因此不能被程序員指定。

 

naked call調用約定:

采用上述4種調用約 定時,如果必要的話,進入函數時編譯器會產生代碼來保存ESI,EDI,EBX,EBP寄存器,退出函數時則產生代碼恢復這些寄存器的內容。naked call不產生這樣的代碼。naked call不是類型修飾符,故必須和_declspec共同使用。

 

關鍵字 __stdcall、__cdecl 和 __fastcall 可以直接加在要輸出的函數前,也可以在編譯環境的 Setting...\C/C++ \Code Generation 項選擇。當加在 輸出函數前的關鍵字與編譯環境中的選擇不同時,直接加在輸出函數前的關鍵字有效。它們對應的命令行參數分別為/Gz、/Gd 和 /Gr。缺省狀態為/Gd,即__cdecl。缺省狀態為__cdecl。

 

4. 名 字修飾約定

"C" 或者 "C++" 函數在內部(編譯和鏈接)通過修飾名識別。修飾名是編譯器在編譯 函數定義或者原型時生成的字符串。有些情況下使用函數的修飾名是必要的,如在模塊定義文件里頭指定輸出"C++"重載函數、構造函數、析構函數,又如在匯編代碼里調用"C""或"C++"函數等。修飾名由函數名、類名、調用約定、返回類型、參數等共同 決定。函數名修飾約定隨編譯種類(C或C++)和調用約定的不同而不同,下面分別說明。

 

C編譯時函數名修飾約定規則:

__stdcall調用約定:

    在輸出函數名前加上一 個下劃線前綴,后面加上一個"@"符號 和其參數的字節數,格式為 _functionname@number。

 

__cdecl調用約定:

    僅在輸出函數名前加上一個下劃線前綴,格式為 _functionname。

 

__fastcall調用約定:

    在輸出函數名前加上一個"@"符號,后面也是一個"@"符號和其參數的字節數,格式為@functionname@number。

 

它們均不改變輸出函數名中的字符大小寫。

 

C++編譯時函數名修飾約定規則:

__stdcall調用約定:

以"?"標識 函數名的開始,后跟函數名;函數名后面以"@@YG"標識參數表的開始,后跟參數表;

參數表以代號表示:

    X——void,

    D——char,

    E——unsigned char,

    F——short,

    H——int,

    I——unsigned int,

    J——long,

    K——unsigned long,

    M——float,

    N——double,

    _N——bool,

    ....

    PA——表示指針,后面的代號表明指針類型,如果相同類型的指針連續出現, 以"0"代替,一個"0"代表一次重復;

 

參數表的第一項為該函數的返回值類型,其后依次為參數的數據類型,指針標識在其所指數據類型前。

參數表后以"@Z"標識整個名字的結束,如果該函數無參數,則以"Z"標識結束。其格式為

    "?functionname@@YG*****@Z" 或 "?functionname@@YG*XZ",

    例如

    int Test1(char *var1,unsigned long)    -----“?Test1@@YGHPADK@Z”

    void Test2()              -----“?Test2@@YGXXZ”(第一個X表示返回類型,第二個X表示參數 類型)

 

__cdecl調用約定:

    規則同上面的_stdcall調用約定,只是參數表的開始標識由上面的"@@YG"變為"@@YA"。VC++對函數的省缺聲明是"__cedcl",將只能被C/C++調用。

 

__fastcall調用約定:

    規則同上面的_stdcall調用約定,只是參數表的開始標識由上面的"@@YG"變為"@@YI"。

 

對于C++的類成員函數(其調用方式是thiscall),函數的名字修飾與非成員的C++函數稍有不同,首先就是在函數名字和參數表之間插入以“@”字符引導的類名;其次是參數表的開始標識不同,公有(public)成員函數的標識是“@@QAE”,保護(protected)成員函數的標識是“@@IAE”,私有(private)成員函數的標識是“@@AAE”,如果函數聲明使用了const關鍵字,則相應的標識應分別為“@@QBE”,“@@IBE”和“@@ABE”。如果參數類型是類實例的引用,則使用“AAV1”,對于const類型的引用,則使用“ABV1”。下面就以類CTest為例說明C++成員函數的名字修飾規則:

class CTest

{

......

private:

    void Function(int);

protected:

    void CopyInfo(const CTest &src);

public:

    long DrawText(HDC hdc, long pos, const TCHAR* text, RGBQUAD color, BYTE bUnder, bool bSet);

    long InsightClass(DWORD dwClass) const;

......

};

對于成員函數Function,其函數修飾名為“?Function@CTest@@AAEXH@Z”,字符串“@@AAE”表示這是一個私有函數。“X”表示返回類型為void,“H”表示參數類型為int類型。

 

成員函數CopyInfo只有一個參數,是對類CTest的const引用參數,其函數修飾名為“?CopyInfo@CTest@@IAEXABV1@@Z”。

 

DrawText是一個比較復雜的函數聲明,不僅有字符串參數,還有結構體參數和HDC句柄參數,需要指出的是HDC實際上是一個HDC__結構類型的指針,這個參數的表示就是“PAUHDC__@@”,其完整的函數修飾名為“?DrawText@CTest@@QAEJPAUHDC__@@JPBDUtagRGBQUAD@@E_N@Z”。

 

InsightClass是一個共有的const函數,它的成員函數標識是“@@QBE”,完整的修飾名就是“?InsightClass@CTest@@QBEJK@Z”。

 

舉例:

比如動態鏈接庫a有以下導出函數:

long MakeFun(long lFun);

動態庫生成的時候采用的函數調用約定是__stdcall,所以編譯生成的a.dll中函數MakeFun的調用約定是_stdcall,也就是函數調用時參數從右向左入棧,函數返回時自己還原堆棧。現在某個程序模塊b要引用a中的MakeFun,b和a一樣使用C++方式編譯,只是b模塊的函數調用方式是__cdecl,由于b包含了a提供的頭文件中MakeFun函數聲明,所以MakeFun在b模塊中被 其它調用MakeFun的函數認為是__cdecl調用方式,b模塊中的 這些函數在調用完MakeFun當然要幫著恢復堆棧啦,可是MakeFun已經在結束時自己恢復了堆棧,b模塊中的函數這樣多此一舉就引起了棧指針錯誤,從而引發堆棧異常。宏觀上的現象就是函數調用沒有問題(因為參數傳遞 順序是一樣的),MakeFun也完成了自己的功能,只是函數返回后引發錯誤。解決的方法也很簡單,只要保證兩個模塊的在編譯時設置相同的函數調用約定就行了。

 

現在再假定兩個模塊在編譯的時候都采用__stdcall調用約定,但是a.dll使用C語言的語法編譯的(C語言方式),所以a.dll的 載入庫a.lib中MakeFun函數的名字修飾就是“_MakeFun@4”。b包含了a提供的頭文件中MakeFun函數聲明,但是由于b采用的是C++語言編譯,所以MakeFun在b模塊中被按照C++的名字修飾規則命名為“?MakeFun@@YGJJ@Z”,編譯過程相安無事,鏈接程序時c++的鏈接器就到a.lib中去找“?MakeFun@@YGJJ@Z”,但是a.lib中只有“_MakeFun@4”,沒有“?MakeFun@@YGJJ@Z”,于是鏈接器就報告:

error LNK2001: unresolved external symbol ?MakeFun@@YGJJ@Z

解決的方法和簡單,就是要讓b模塊知道這個函數是C語言編譯的,extern "C"可以做到這一點。一個采用C語言編譯的庫應該考慮到使用這個庫的程序可能是C++程序(使用C++編譯器),所以在設計頭文件時應該注意這一點。通常應該這樣聲明 頭文件:

#ifdef _cplusplus

extern "C" {

#endif

long MakeFun(long lFun);

#ifdef _cplusplus

}

#endif

這樣C++的編譯器就知道MakeFun的修飾名是“_MakeFun@4”,就不會有鏈接錯誤了。

 

許多人不明白,為什么我使用的編譯器都是VC的編譯器還會產生“error LNK2001”錯誤?其實,VC的編譯器會根據源文件的擴展名選擇編譯方式,如果文件的擴展名是“.C”,編譯器會采用C的語法編譯,如果擴展名是“.cpp”,編譯器會使用C++的語法編譯程序,所以,最好的方法就是使用extern "C"。

 

5. 單看函數的名字修飾

有兩種方式可以檢查你的程序中的函數的名字修飾:使用編譯輸出列表或使用Dumpbin工具。使用/FAc,/FAs或/FAcs命令行參數可以讓編譯器輸出函數或變量名字列表。使用dumpbin.exe /SYMBOLS命令也可以獲得obj文件或lib文件中的函數或變量名字列表。此外,還可以使用 undname.exe 將修飾名轉換為未修飾形式。

from:
http://patmusing.blog.163.com/blog/static/13583496020103233446784/

posted on 2010-04-28 00:10 chatler 閱讀(631) 評論(0)  編輯 收藏 引用 所屬分類: windows
<2025年11月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

常用鏈接

留言簿(10)

隨筆分類(307)

隨筆檔案(297)

algorithm

Books_Free_Online

C++

database

Linux

Linux shell

linux socket

misce

  • cloudward
  • 感覺這個博客還是不錯,雖然做的東西和我不大相關,覺得看看還是有好處的

network

OSS

  • Google Android
  • Android is a software stack for mobile devices that includes an operating system, middleware and key applications. This early look at the Android SDK provides the tools and APIs necessary to begin developing applications on the Android platform using the Java programming language.
  • os161 file list

overall

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久国产欧美| 欧美精品在线一区| 国产视频欧美视频| 亚洲欧美日韩在线高清直播| 亚洲色无码播放| 国产精品青草久久| 欧美在线免费看| 欧美一区二区三区婷婷月色| 狠狠噜噜久久| 亚洲人成亚洲人成在线观看图片| 欧美精品aa| 午夜激情一区| 久久嫩草精品久久久久| 亚洲精品免费在线播放| 一区二区免费在线视频| 国产欧美综合在线| 欧美高清视频在线| 欧美色图天堂网| 久久精品综合网| 欧美大片va欧美在线播放| 宅男精品导航| 久久精品一区二区三区不卡牛牛 | 欧美一区二区视频免费观看| 韩国免费一区| 亚洲美女中出| 精品成人在线视频| 99在线精品视频在线观看| 国产欧美日韩在线| 最新日韩在线视频| 国产视频在线观看一区二区三区| 欧美a级片网站| 国产精品久久国产愉拍 | 亚洲影院高清在线| 久久国产精品久久w女人spa| 亚洲美女精品一区| 久久成人这里只有精品| 中文久久精品| 美女主播一区| 久久久久久久久伊人| 欧美日韩三区| 亚洲第一区色| 狠狠色综合网| 亚洲欧美一区二区在线观看| 亚洲精品在线二区| 久久久精品网| 欧美专区第一页| 国产精品久久久久久久午夜 | 午夜视频在线观看一区二区| 嫩草国产精品入口| 另类成人小视频在线| 国产精品每日更新在线播放网址| 欧美成人首页| 在线精品视频免费观看| 午夜精品免费| 欧美一级大片在线免费观看| 欧美日韩一区二区三区视频| 亚洲韩国一区二区三区| 精品粉嫩aⅴ一区二区三区四区| 亚洲综合国产| 午夜一区二区三区不卡视频| 欧美视频日韩| 一本色道**综合亚洲精品蜜桃冫| 亚洲精品系列| 欧美精品一区二区三区高清aⅴ| 欧美激情精品久久久久久蜜臀 | 国产精品日韩欧美大师| 日韩视频免费看| 在线视频日本亚洲性| 欧美日韩成人综合在线一区二区 | 久久激情五月丁香伊人| 国产乱人伦精品一区二区| 亚洲视频欧美在线| 亚洲免费影视| 国产目拍亚洲精品99久久精品| 亚洲在线成人| 久久久久久久久久久久久女国产乱| 国产一区二区你懂的| 久久国产精品免费一区| 蜜桃久久精品一区二区| 亚洲激情网站| 欧美午夜片在线观看| 制服丝袜亚洲播放| 久久国产黑丝| 亚洲国产精品成人综合| 欧美—级高清免费播放| 一二三区精品| 香蕉免费一区二区三区在线观看 | 亚洲第一精品久久忘忧草社区| 麻豆av一区二区三区久久| 亚洲国产精品一区在线观看不卡| 一区二区三区精品视频| 国产精品大全| 久久精品国产一区二区三区免费看| 美女视频一区免费观看| 亚洲靠逼com| 国产精品腿扒开做爽爽爽挤奶网站 | 国产日韩欧美日韩| 久久久久久9| 日韩视频永久免费| 欧美在线免费视屏| 亚洲国产精品传媒在线观看 | 久久精品国产亚洲a| 亚洲激情偷拍| 欧美专区第一页| 一区二区电影免费在线观看| 国产欧美日韩不卡免费| 欧美激情一区二区三区| 午夜精品福利电影| 91久久国产精品91久久性色| 欧美一区二区网站| 亚洲精品国产精品国自产观看| 国产精品看片资源| 美女尤物久久精品| 欧美亚洲综合在线| 亚洲精品一区二区三区在线观看 | 亚洲肉体裸体xxxx137| 国产精品一区二区a| 欧美—级a级欧美特级ar全黄| 欧美一区二区三区四区在线观看| 亚洲精品免费在线播放| 麻豆成人精品| 欧美专区在线| 亚洲欧美日韩国产| 日韩视频免费在线观看| 一区二区三区中文在线观看| 国产精品视频免费一区| 欧美精品福利在线| 老牛嫩草一区二区三区日本 | 亚洲高清视频中文字幕| 久久亚洲二区| 久久免费99精品久久久久久| 亚洲免费在线视频| 亚洲天堂视频在线观看| 亚洲乱码视频| 亚洲毛片一区| 亚洲巨乳在线| 亚洲精品美女免费| 亚洲精品免费在线观看| 91久久久在线| 亚洲日本aⅴ片在线观看香蕉| 在线观看视频日韩| 在线观看av一区| 在线成人亚洲| 亚洲第一成人在线| 亚洲观看高清完整版在线观看| 在线观看日韩| 亚洲人成网站在线播| 亚洲国产小视频| 亚洲精品乱码久久久久久蜜桃麻豆| 亚洲国产精品va在线看黑人动漫| 狠色狠色综合久久| 在线观看中文字幕不卡| 亚洲电影毛片| 亚洲精品欧美专区| 一本大道av伊人久久综合| 一二三区精品福利视频| 一区二区三区www| 亚洲欧美日韩国产综合精品二区 | 亚洲电影免费观看高清| 一区二区在线免费观看| 亚洲国产欧美在线人成| 日韩视频中文字幕| 亚洲欧美精品伊人久久| 午夜精品久久久久影视| 久久久精品国产免大香伊| 美女尤物久久精品| 亚洲欧洲视频| 亚洲欧美另类综合偷拍| 久久精品免费播放| 欧美国产视频日韩| 国产精品九九久久久久久久| 国产字幕视频一区二区| 亚洲欧洲视频在线| 亚洲综合二区| 麻豆久久婷婷| 亚洲精品一级| 久久精品一区中文字幕| 欧美精品日韩精品| 国产一区二区三区丝袜| 日韩视频免费看| 久久美女性网| 99在线精品观看| 久久一区二区三区四区| 国产精品电影网站| 亚洲第一天堂av| 亚洲欧美日韩中文视频| 免费成人小视频| 亚洲在线免费观看| 欧美精品久久久久a| 国产在线精品自拍| 亚洲一二三区在线| 欧美r片在线| 午夜精品久久久久久| 欧美日韩国产影片| 永久免费毛片在线播放不卡| 亚洲欧美日韩精品久久| 亚洲国产婷婷| 久久精品午夜| 国产欧美日韩在线视频| 亚洲伊人网站|