小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

64位環(huán)境中.net framework的運(yùn)行機(jī)制探討

 昵稱10504424 2013-02-19
近在編寫.net應(yīng)用程序時(shí),發(fā)現(xiàn)某些平臺(tái)下無法加載SQLite DLL的問題。

癥狀表現(xiàn)為:

a. 本地Windows 7/8 64bit開發(fā)環(huán)境完全正常。
b. 某些Windows 7 64bit用戶的計(jì)算機(jī)無法加載System.Data.SQLite.DLL。
c. 極個(gè)別Windows XP的計(jì)算機(jī)無法加載該DLL。


無法加載DLL時(shí),均報(bào)BadImageFormatException異常,甚至直接被Windows關(guān)閉而無法采集異常信息。奇怪的是在當(dāng)前目錄包含了這個(gè)DLL文件,所以理應(yīng)能成功加載才是。

由于各種場(chǎng)景的組合在一起,一時(shí)很難判斷問題出于何處。起初筆者努力嘗試各種方法試圖在本機(jī)重現(xiàn),也均告失敗。在偶然的機(jī)會(huì),筆者刪除了本機(jī)所有與SQLite相關(guān)的組件,問題成功重現(xiàn)。

絕望之中燃起了一點(diǎn)希望。我發(fā)現(xiàn)自己曾經(jīng)安裝了三個(gè)與SQLite相關(guān)的組件:

Java代碼 復(fù)制代碼 收藏代碼
  1. SQLite-1.0.66.0-setup.exe   
  2. sqlite-netFx35-setup-bundle-x64-2008-1.0.82.0.exe   
  3. sqlite-netFx35-setup-bundle-x86-2008-1.0.82.0.exe  


反復(fù)多次后確認(rèn)了以下內(nèi)容:

Java代碼 復(fù)制代碼 收藏代碼
  1. SQLite-1.0.66.0-setup.exe - 無效果   
  2. sqlite-netFx35-setup-bundle-x86-2008-1.0.82.0.exe - 無效果   
  3. sqlite-netFx35-setup-bundle-x64-2008-1.0.82.0.exe - 成功  


看來,用戶系統(tǒng)上沒有sqlite-netFx35-setup-bundle-x64-2008-1.0.82.0.exe,所以導(dǎo)致運(yùn)行失敗。經(jīng)仔細(xì)檢查,這個(gè)包在系統(tǒng)GAC中安裝了64位DLL,而之前我發(fā)布的目錄中包含的是32位DLL文件。一切真相大白,將64位版本與32位版本分開發(fā)布,問題解決!

到這里,本該可以松口氣了,但我心中仍然充滿疑惑:

(1) 在64位系統(tǒng)上,我的.net應(yīng)用到底算是32位的還是64位的?

(2) 32位應(yīng)用程序照理可以在64位系統(tǒng)上正常運(yùn)行,為什么當(dāng)前目錄的DLL沒有加載成功?

(3) 為何以前調(diào)用的第三方DLL從沒有發(fā)生32/64位的問題,只有這個(gè)DLL如此特別?

(4) .net的加載DLL的順序是什么,到底以哪個(gè)優(yōu)先?


經(jīng)過一番認(rèn)真的Google,上述迷團(tuán)一一破解。

(1) 在64位系統(tǒng)上,.net程序是通常以64位程序運(yùn)行的。Windows不會(huì)啟用Wow。這可以從任務(wù)管理器中看到(在64位系統(tǒng)中運(yùn)行的32位程序?qū)⒁?32或“32位”標(biāo)記)。


然后事情并非還如此簡(jiǎn)單。.net程序目前有以下幾種處理器架構(gòu):

Java代碼 復(fù)制代碼 收藏代碼
  1. Any CPU(處理器無關(guān)的純MSIL代碼)   
  2. x64(僅64位處理器,又稱AMD64)   
  3. x86(僅32位處理器)   
  4. IA64(僅IA64位處理器)  


之前所說的“通?!?,即指Any CPU。這樣的程序在32位系統(tǒng)上以32位模式運(yùn)行,在64位系統(tǒng)上以64位模式運(yùn)行。這時(shí),而標(biāo)識(shí)為特定處理器的,只能在相應(yīng)的模式上運(yùn)行。

更詳細(xì)地,使用corflags工具可以看到以下信息:


Java代碼 復(fù)制代碼 收藏代碼
  1. D:\Lib\x64\>corflags System.Data.SQLite.DLL     
  2. Microsoft (R) .NET Framework CorFlags Conversion Tool.  Version  2.0.50727.42     
  3. Copyright (c) Microsoft Corporation.  All rights reserved.     
  4.      
  5. Version   : v2.0.50727     
  6. CLR Header: 2.5     
  7. PE        : PE32+     
  8. CorFlags  : 24     
  9. ILONLY    : 0     
  10. 32BIT     : 0     
  11. Signed    : 1   


Java代碼 復(fù)制代碼 收藏代碼
  1. D:\Lib\x86\>corflags System.Data.SQLite.DLL     
  2. Microsoft (R) .NET Framework CorFlags Conversion Tool.  Version  2.0.50727.42     
  3. Copyright (c) Microsoft Corporation.  All rights reserved.     
  4.      
  5. Version   : v2.0.50727     
  6. CLR Header: 2.5     
  7. PE        : PE32     
  8. CorFlags  : 24     
  9. ILONLY    : 0     
  10. 32BIT     : 0     
  11. Signed    : 1  


ILONLY: 在映像中是否只包含了IL代碼。1表示純IL代碼,0表示包含了Native代碼。
32BIT: 即使是純IL代碼,在32位與64位環(huán)境中運(yùn)行還是有區(qū)別的。這個(gè)標(biāo)記用于區(qū)分x86與Any CPU。
PE: 32位為PE32,64位為PE32+。這個(gè)用于區(qū)分32位與64位映象。


Java代碼 復(fù)制代碼 收藏代碼
  1. Any CPU:PE = PE32  and 32BIT = 0  
  2. x86:    PE = PE32  and 32BIT = 1  
  3. x64:    PE = PE32+ and 32BIT = 0  


由于之前我們?cè)噲D在64位進(jìn)程上加載的32位DLL,其ILONLY=0,即包含平臺(tái)相關(guān)代碼,因此無法加載而拋出錯(cuò)誤?!咀ⅲ和ㄟ^現(xiàn)象推測(cè),需要跟蹤.net Framework代碼證實(shí)】

(2) 這個(gè)問題通過上述剖析,已經(jīng)很清楚了。要說明的是,如果想繞過64位DLL帶來的麻煩,將主程序也編譯成x86而不是Any CPU,也是可以在64位系統(tǒng)上運(yùn)行的。這時(shí),操作系統(tǒng)將啟用Wow模式啟動(dòng)這個(gè)進(jìn)程。

(3) 這個(gè)SQLite的DLL混合了IL和Native代碼,必須嚴(yán)格地對(duì)應(yīng)平臺(tái)調(diào)用。

(4) .net加載程序集的順序:

1、 在GAC(Global Assembly Cache)中搜索相應(yīng)版本的DLL;
2、 配置文件(web.config或app.config);
3、 應(yīng)用程序(.exe)當(dāng)前目錄下;

但事實(shí)上有可能比這個(gè)順序更為復(fù)雜,詳見:
http://msdn.microsoft.com/en-us/library/aa720133.aspx 及參考文獻(xiàn)7。

之前,在我開發(fā)環(huán)境中,由于本地GAC中已經(jīng)包含了正確的x64版本,所以能正確運(yùn)行。但復(fù)制到別人的64位機(jī)器上時(shí)就出問題了。而有些XP機(jī)器上安裝了錯(cuò)誤的小版本,因此也出現(xiàn)加載失敗的現(xiàn)象。

最后,補(bǔ)充說明一下GAC的位置:\Windows\assembly。使用“我的電腦”打開這個(gè)目錄時(shí),看到的是所有.net全局程序集的列表,這是Windows特殊處理后的結(jié)果。只有通過命令行才能看到這個(gè)目錄中分成了GAC_32, GAC_64, GAC_MSIL等幾個(gè)子目錄。這幾個(gè)目錄正是前文所述不同處理器架構(gòu)的幾種DLL。

補(bǔ)充:
關(guān)于之前[c]的問題的解決方案:

后來發(fā)現(xiàn),System.Data.SQLite.DLL版本1.0.66均能正常工作,但1.0.82在某些Windows XP上無法工作。由于官方網(wǎng)站對(duì)1.0.82的解釋大多關(guān)注在x86與x64的區(qū)別,我一度仍然以為是處理器架構(gòu)造成的。最后,通過depends工具查看發(fā)現(xiàn),1.0.82版的DLL引用了MSVCR90.DLL。而出問題的機(jī)器上未安裝VC2008 Runtime,自然無法找到該DLL了。

解決的辦法有兩個(gè):使用1.0.66版,或在XP上安裝VC2008運(yùn)行包:
http://www.microsoft.com/zh-cn/download/details.aspx?id=29

由于之前對(duì)64位平臺(tái)應(yīng)用的理解有限,文中很多內(nèi)容通過實(shí)驗(yàn)推測(cè),有可能和Microsoft官方表述有不一致或者錯(cuò)誤的地方。歡迎大家指正!


參考文獻(xiàn):

1、http://msdn.microsoft.com/en-us/magazine/dd727509.aspx
2、http://blogs./b/gauravseth/archive/2006/03/07/545104.aspx
3、http://blogs./b/junfeng/archive/2004/08/11/212555.aspx
4、http://blogs./b/junfeng/archive/2004/09/12/228635.aspx
5、http://blog.csdn.net/cstod/article/details/4887049
6、http:///questions/6507675/gac-32bit-vs-64bit
7、http://blog.csdn.net/wangjunhe/article/details/6692194

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多