• <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>

            weibing

            隨想Visual C++ “導(dǎo)出/導(dǎo)入類的嚴(yán)重危害”

            VC中有一個關(guān)鍵字__declspec(dllexport), 其目的很簡單,就是導(dǎo)出符號,供其它可執(zhí)行模塊使用,主要用于動態(tài)鏈接庫(DLL), 然而也可用于EXE模塊

            與此相對應(yīng),__declspec(dllimport), 將指明由動態(tài)鏈接庫導(dǎo)入符號,除了導(dǎo)入全局變量/類的靜態(tài)成員變量,很多時候可以忽略, 這個時候?qū)ふ曳柕膬?yōu)先級將有所不同
             

            當(dāng)這兩個關(guān)鍵字配合類使用,將會產(chǎn)生比較尷尬的問題了

             

            DLL:

            struct __declspec(dllexport) A

            {

                void TestInline()

            {

                printf(from dll\n);

            }

            };

             

            EXE:

            struct __declspec(dllimport) A

            {

            void TestInline()

            {

            printf(from exe\n);

            }

            };

             

            int main()

            {

                A obj;

                obj.TestInline(); //輸出 from dll!

             

                return 0;

            }

             

            危害1:

            A中的內(nèi)聯(lián)函數(shù)全部失效

             

            這當(dāng)然可以從符號鏈接表中發(fā)現(xiàn)鏈接符號的蹤跡來表明內(nèi)聯(lián)函數(shù)失效了,不過有一個更簡單的方法,我們可以在EXE的代碼中把TestInline內(nèi)聯(lián)函數(shù)的定義代碼加以簡單修改,讓其輸出其它的字符串測試,這個時候運(yùn)行會發(fā)現(xiàn),輸出的字符串仍然是from dll(注意編譯為Release發(fā)行版, DEBUG版會將內(nèi)聯(lián)函數(shù)作為普通函數(shù)處理), 這就說明了,內(nèi)聯(lián)函數(shù)被完全忽略了。如果這個時候,還能想到TestInline的定義代碼還有什么作用的話,那就是白白消耗編譯的時間,編譯期間編譯器辛辛苦苦生成的代碼,鏈接器會毫不留情地忽略掉。

             

            很顯然,忽略掉內(nèi)聯(lián)函數(shù)的代碼,會有一個直接的副作用,那就是使應(yīng)用程序的運(yùn)行期變緩慢,特別是內(nèi)聯(lián)函數(shù)被大量在循環(huán)內(nèi)調(diào)用,而這個內(nèi)聯(lián)當(dāng)成普通函數(shù)處理了

             

            C++運(yùn)行庫中有大量的內(nèi)聯(lián)成員函數(shù),除了模板類以外(當(dāng)然,非完全特化的模板類不可能支持導(dǎo)出的),基本上都是以導(dǎo)出類的形式導(dǎo)出,這樣也就意味著,動態(tài)鏈接C++運(yùn)行庫的程序,這類內(nèi)聯(lián)函數(shù)全部失效,編譯時間可一點(diǎn)沒少。

             

            危害2:

            私有成員函數(shù),以及原本不想導(dǎo)出的函數(shù)(沒有多少重用價值,導(dǎo)出后還要承擔(dān)維護(hù)版本兼容性的責(zé)任),也被”不知不覺”
            地導(dǎo)出了,對于私有(private)成員函數(shù), 導(dǎo)出到外面有什么用呢?占據(jù)了符號表的一個位置,可是誰又能調(diào)用到呢?
            如果要想調(diào)用,看來要強(qiáng)制把private變?yōu)閜ublic了,但是VC的符號形成機(jī)制包含了public/private/protected,
            也就是通過了編譯也無法通過鏈接,唯一可能的辦法就是,修改DLL頭文件,在類里面增加”friend”, 在EXE端,
            改變共享庫DLL頭文件的辦法,很顯然不是個正規(guī)方案

            另外,導(dǎo)出了這些“無法調(diào)用”的函數(shù),也影響了鏈接器的優(yōu)化。對于這些函數(shù),如果DLL模塊內(nèi)部也沒有調(diào)用到,
            本可以完全把這些代碼優(yōu)化掉,但是由于導(dǎo)出,鏈接器將無能為力, 這也直接增加了DLL文件的體積

            由此想到的:

            MFC/ATL動態(tài)庫似乎了解到這個問題,所以,它們寧可一個一個成員函數(shù)進(jìn)行符號導(dǎo)出,也沒有進(jìn)行整個類的導(dǎo)出,
            為什么它們不把這個方式推薦給VC動態(tài)運(yùn)行庫呢?

            VC傳統(tǒng)靜態(tài)鏈接運(yùn)行庫的方式雖然有某種弊端,但是卻可以完全避開上述提到的問題,而且脫離了版本型DLL的依賴(MSVCR71.dll, MSVCP71.dll, MSVCR90.dll, MSVCP90.dll), 對于這類DLL的依賴,將給以后程序升級帶來隱含并難以解決的問題,大家可以考慮如下情形

            版本1:A.exe依賴于B.dll, 并且它們同時依賴于msvcp71.dll

            版本2: 由于A采用了新的VC版本進(jìn)行編譯,A.exe現(xiàn)在依賴于msvcp90.dll了,B.dll沒有升級,仍然依賴msvcp71.dll

            這個時候,進(jìn)程中的內(nèi)存結(jié)構(gòu)產(chǎn)生了微妙的變化,舉例來說,原來msvcp71.dll中的全局變量(例如cout)同時被A.exe和B.dll使用。現(xiàn)在呢,A.exe使用的是msvcp90.dll中的cout, B.dll使用的還是msvcp71.dll中的cout, 這種耦合的變化,將會導(dǎo)致程序執(zhí)行邏輯的變化(如果你運(yùn)氣好,也許會沒有問題的),例如,如果你在A中設(shè)置了cout的格式,然后調(diào)用B的接口,最后B的接口通過cout輸出,版本2與版本1將會拿到不同的執(zhí)行效果(源代碼可一點(diǎn)沒變哦,僅僅是換了個編譯器編譯)。大型程序邏輯將是非常復(fù)雜的,看來還是不要升級編譯器進(jìn)行編譯的好,因?yàn)檫@將導(dǎo)致dll依賴關(guān)系的變化,這真是個無奈的選擇

             

            混合編譯選項(xiàng) /clr看來要考慮允許靜態(tài)鏈接運(yùn)行庫了(現(xiàn)在的VC版本只能動態(tài)鏈接運(yùn)行庫的),因?yàn)檫\(yùn)行庫DLL存在版本和效率缺陷

             

            大家有沒有發(fā)現(xiàn)LINUX操作系統(tǒng)下的so文件一般比windows下的要大很多,其中一個原因是這個模型相當(dāng)于默認(rèn)全部導(dǎo)出,即使是全局函數(shù)也是一樣,哪怕你臨時寫一個沒意義的函數(shù),忘記去掉了,也一并導(dǎo)出,雖然你并沒有給外界頭文件,告訴這個接口如何被調(diào)用,但是這個接口已經(jīng)事實(shí)存在了。雖然這樣會簡化一些工作,但是個人覺得,是非常不負(fù)責(zé)任的,特別是現(xiàn)代的應(yīng)用大都是多任務(wù)模塊化的,這樣做潛在地多吃掉不少內(nèi)存和硬盤,而且對于版本兼容性,將帶來麻煩。我對LINUX了解不多,不知道是否有支持指定導(dǎo)出函數(shù)的方法呢?

            COM(Component Object Model), 也許有很多其它弊端,但卻解決了上述問題,而且可以拿掉DLL文件名中描述版本的丑陋數(shù)字

             

            個人認(rèn)為,發(fā)展C++的二進(jìn)制接口標(biāo)準(zhǔn)ABI(Application Binary Interface)是非常重要的,COM應(yīng)該算一個ABI標(biāo)準(zhǔn)吧。總是靜態(tài)地依賴源代碼作為可重用模塊,真的弊端很大,多任務(wù)時占用的磁盤和內(nèi)存也會增加。托管編程模型毫無疑問解決了這個問題,當(dāng)然也帶來了其它方面的一些問題。C++在編程模型上可以說比托管編程模型要簡單很多,但缺少一個二進(jìn)制標(biāo)準(zhǔn)。解決這個問題將比在語言層面增加幾個關(guān)鍵字要重要很多

            posted on 2011-08-01 23:54 魏兵 閱讀(3651) 評論(13)  編輯 收藏 引用

            Feedback

            # re: 隨想Visual C++ “導(dǎo)出/導(dǎo)入類的嚴(yán)重危害” 2011-08-02 02:35 fklz

            暈死,顯然是你傻逼不會用!真沒見過這么傻逼還自作聰明的  回復(fù)  更多評論   

            # re: 隨想Visual C++ “導(dǎo)出/導(dǎo)入類的嚴(yán)重危害” 2011-08-02 14:47 Enic

            樓上非常正確,,,  回復(fù)  更多評論   

            # re: 隨想Visual C++ “導(dǎo)出/導(dǎo)入類的嚴(yán)重危害” 2011-08-02 16:24 樂購網(wǎng)

            來好好的學(xué)習(xí)一下。  回復(fù)  更多評論   

            # re: 隨想Visual C++ “導(dǎo)出/導(dǎo)入類的嚴(yán)重危害” 2011-08-02 18:46 空明流轉(zhuǎn)

            你用啥沒危害。。。  回復(fù)  更多評論   

            # re: 隨想Visual C++ “導(dǎo)出/導(dǎo)入類的嚴(yán)重危害” 2011-08-02 19:44 bennycen

            看成了“人類的嚴(yán)重危害”  回復(fù)  更多評論   

            # re: 隨想Visual C++ “導(dǎo)出/導(dǎo)入類的嚴(yán)重危害”[未登錄] 2011-08-03 09:19 劍孤寒

            首先,內(nèi)聯(lián)函數(shù)全部失效并不是導(dǎo)出類的錯,而是用的人的錯,如果你要內(nèi)聯(lián)就不應(yīng)該用導(dǎo)出類
            其次,私有函數(shù)導(dǎo)出并不會顯著增加dll體積,如果dll體積很重要也是有辦法回避這個問題的,另外,私有函數(shù)導(dǎo)不導(dǎo)出跟維護(hù)沒啥關(guān)系吧,都是你內(nèi)部用的,你不用導(dǎo)出類內(nèi)部函數(shù)出問題還不是也要維護(hù)
            最后,靜態(tài)鏈接庫如果用了stl也是依賴crt的  回復(fù)  更多評論   

            # re: 隨想Visual C++ “導(dǎo)出/導(dǎo)入類的嚴(yán)重危害” 2011-08-03 10:09 cr

            不是這么用的。  回復(fù)  更多評論   

            # re: 隨想Visual C++ “導(dǎo)出/導(dǎo)入類的嚴(yán)重危害” 2011-08-03 10:48 terminator

            傻逼成這樣居然還能長篇大論?夠寒磣人的。  回復(fù)  更多評論   

            # re: 隨想Visual C++ “導(dǎo)出/導(dǎo)入類的嚴(yán)重危害”[未登錄] 2011-08-03 19:54 cexer

            那些出口就罵人的,都是些畜牲嗎?你爹媽沒教過你怎么說人話?  回復(fù)  更多評論   

            # re: 隨想Visual C++ “導(dǎo)出/導(dǎo)入類的嚴(yán)重危害”[未登錄] 2011-08-04 04:37 cexer

            搞笑啊,樓上你冒用ID很光彩?看來被人罵傻逼沒罵錯  回復(fù)  更多評論   

            # re: 隨想Visual C++ “導(dǎo)出/導(dǎo)入類的嚴(yán)重危害”[未登錄] 2011-08-04 09:11 a

            人家理解的不對,大家指出問題、提供解決辦法就行,何必罵人呢?罵完了對你有什么好處啊。朋友多了路好走。樹個敵人對自己有益處?年輕人怎么這么多火焰呢?這么有活力,還不如去改造這個社會做貢獻(xiàn)呢。在團(tuán)隊(duì)方面來講,罵人首先就沒有團(tuán)隊(duì)精神,不合作啊。  回復(fù)  更多評論   

            # re: 隨想Visual C++ “導(dǎo)出/導(dǎo)入類的嚴(yán)重危害” 2011-08-05 13:07 欲三更

            1.按照lz的邏輯,F(xiàn)22戰(zhàn)機(jī)的嚴(yán)重危害是它們太費(fèi)油——你都使用導(dǎo)出類了,還在乎什么內(nèi)聯(lián)函數(shù)?

            2.stl代碼里面什么時候有導(dǎo)出類的符號了?VC的crt說的是C庫。

            3.這個時候,進(jìn)程中的內(nèi)存結(jié)構(gòu)產(chǎn)生了微妙的變化……以我的經(jīng)驗(yàn),任何一個頭腦正常的工程師都不會做這樣的事情!

            4.現(xiàn)在談COM之類的東西,我怎么感覺這是5年前的文章?  回復(fù)  更多評論   

            # re: 隨想Visual C++ “導(dǎo)出/導(dǎo)入類的嚴(yán)重危害” 2011-08-05 20:00 fly C++

            @劍孤寒
            這個問題我深入考察過MFC動態(tài)庫與CRT動態(tài)庫的不同,發(fā)現(xiàn)MFC頭文件中的內(nèi)聯(lián)成員函數(shù)是有效的(這可以通過簡單修改頭文件中的定義代碼,看運(yùn)行時的效果可以證明,你修改的代碼產(chǎn)生作用,就說明并沒有用到DLL內(nèi)部的定義),其原因是MFC的頭文件并沒有使用戶通過__declspec(dllimport) class 的方式使用,但是CRT動態(tài)庫,卻是隱含的讓使用者采用這種方式,其結(jié)果是,當(dāng)用戶動態(tài)鏈接CRT時,其非模板類內(nèi)聯(lián)成員函數(shù)(模板類不能真正導(dǎo)出定義),實(shí)際上都不可能作為內(nèi)聯(lián)函數(shù)了,因?yàn)槭褂玫亩际荄LL內(nèi)部的定義代碼(這也可以通過上面的方法發(fā)現(xiàn)),這將一定程度上影響程序執(zhí)行效率,并使CRT導(dǎo)出接口龐大(內(nèi)聯(lián)函數(shù)導(dǎo)出沒有意義,因?yàn)楸┞兜念^文件已經(jīng)有定義代碼了,為什么還要使用DLL的定義體呢,而且會傷害運(yùn)行效率)。我碰到過一個程序,靜態(tài)鏈接CRT比動態(tài)鏈接CRT要快非常多,并不是程序加載DLL產(chǎn)生的時間延遲,而是程序運(yùn)行起來之后產(chǎn)生的問題,花了非常多的時間,才確定是這個原因。如果大家有興趣,我可以貼出一段代碼

            關(guān)于接口維護(hù), 對于C語言寫的DLL, 只是導(dǎo)出一部分外界需要用到的函數(shù),如果C++導(dǎo)出了所有內(nèi)部定義的東西,不管外界是否要用到,而且私有成員函數(shù)對于外界也不可能用到,多少感覺有些那個

            以上謹(jǐn)代表個人觀點(diǎn)的  回復(fù)  更多評論   



            只有注冊用戶登錄后才能發(fā)表評論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            My Links

            Blog Stats

            常用鏈接

            留言簿

            隨筆檔案

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            精品久久人人爽天天玩人人妻| 久久亚洲欧洲国产综合| 91麻豆精品国产91久久久久久| 国产精品无码久久久久| 久久99精品久久久久久久不卡 | 性做久久久久久久久浪潮| www性久久久com| 99久久精品国产高清一区二区| 国产精品久久久久久久人人看| 久久久久这里只有精品| 一本色道久久88加勒比—综合| 久久99精品国产99久久6男男| 国产成人无码久久久精品一| 99蜜桃臀久久久欧美精品网站| 国产69精品久久久久APP下载| 亚洲国产精品一区二区三区久久| 久久亚洲国产成人精品无码区| 久久人人爽人人爽人人片AV东京热| 欧美激情精品久久久久久久 | 91久久精品国产免费直播| 国产精品久久久久9999高清| 青青草原综合久久| 色综合色天天久久婷婷基地| 日本精品久久久中文字幕| 久久久久久噜噜精品免费直播| 久久久久久曰本AV免费免费| 久久99精品国产麻豆宅宅| 久久久久久人妻无码| 99精品国产在热久久无毒不卡| 国产巨作麻豆欧美亚洲综合久久| 青青热久久国产久精品| 久久精品极品盛宴观看| 91精品国产乱码久久久久久| AAA级久久久精品无码片| 久久精品国产欧美日韩| 综合久久国产九一剧情麻豆| 国内精品久久久久久野外| 久久婷婷五月综合色99啪ak| 亚洲va久久久噜噜噜久久天堂| 久久国产成人| 中文字幕乱码久久午夜|