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

posts - 319, comments - 22, trackbacks - 0, articles - 11
  C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

DLL導(dǎo)出類的問題

Posted on 2011-08-10 07:23 RTY 閱讀(843) 評論(0)  編輯 收藏 引用 所屬分類: C/C++ 、Windows
DLL導(dǎo)出類的問題

http://www.diybl.com/course/3_program/c++/cppjs/200833/102641.html
DLL動態(tài)鏈接庫是程序復(fù)用的重要方式,DLL可以導(dǎo)出函數(shù),使函數(shù)被多個程序復(fù)用,DLL中的函數(shù)實現(xiàn)可以被修改而無需重新編譯和連接使用該DLL的應(yīng)用程序。作為一名面向?qū)ο蟮某绦騿T,希望DLL可以導(dǎo)出類,以便在類的層次上實現(xiàn)復(fù)用。所幸的是,DLL確實也可以導(dǎo)出類。

然而事實卻沒這么簡單,導(dǎo)出類的DLL在維護和修改時有很多地方必需很小心,增加成員變量、修改導(dǎo)出類的基類等操作都可能導(dǎo)致意想不到的后果,也許
用戶更新了最新版本的DLL庫后,應(yīng)用程序就再也不能工作了。這就是著名的DLL Hell(DLL地獄)問題。

DLL地獄問題是怎么產(chǎn)生的呢?看下面的例子,假設(shè)DLL有一個導(dǎo)出類ClassD1:
class ClassD
{
       public:
int GetInt();
              private:
int m_i;
};
int ClassD::GetInt()
{
       return m_i;
}

應(yīng)用程序使用現(xiàn)在的代碼來使用這個類:
ClassD d;
printf(“%d”, d.GetInt());
 
程序進行正正常,沒有什么問題。后來DLL需要升級,對ClassD進行了修改,增加了一個成員變量,如下:
class ClassD // 修改后
{
       public:
int GetInt();
              private:
                     int m_i2;
int m_i;
};

把新的DLL編譯連接完成后,復(fù)制到應(yīng)用程序目錄,這個倒楣的應(yīng)用程序調(diào)用GetInt方法恐怕再也無法得正確的值了。事實上它還算幸運的,如果GetInt的實現(xiàn)改成如下這樣,那么它馬上就要出錯退出了。
int ClassD::GetInt() // 修改后
{
       return m_i++;
}

這樣的事情,稱它是個地獄(Hell)一點也不夸張。為什么會出錯呢?我們要先從類實例的創(chuàng)建開始,看看使用一個類的工作過程。

首先,程序語句“ClassD d;”為這個類申請一塊內(nèi)存。這塊內(nèi)存保存該類的所有成員變量,以及虛函數(shù)表。內(nèi)存的大小由類的聲明決定,在應(yīng)用程序編譯時就已經(jīng)確定。

然后,當調(diào)用“d.GetInt()”時,把申請的這一塊內(nèi)存做為this指針傳給GetInt函數(shù),GetInt函數(shù)從this指向的位置開始,加上m_i應(yīng)有的偏移量,計算m_i所在的內(nèi)存位置,并從該位置取數(shù)據(jù)返回。m_i相對this的偏移量是由m_i在類中定義的位置決定的,定義在前的成員變量在內(nèi)存中也更靠前。這個偏移量在DLL編譯時確定。

當ClassD的定義改為修改后的狀態(tài)時,有些東西變了。

第一個變的是內(nèi)存的大小。因為修改后的ClassD多了一個成員變量,所以內(nèi)存也變大了。然而這一點應(yīng)用程序并不知道。

第二個變的是m_i的偏移地址。因為在m_i之前定義了一個m_i2,m_i的實現(xiàn)偏移地址實際已經(jīng)靠后了。所以d.GetInt()訪問的將是原來m_i后面的那個位置,而這個位置已經(jīng)超出原來那塊內(nèi)存的后部范圍了。

很顯然,在更換了DLL后,應(yīng)用程序還按原來的大小申請了一塊內(nèi)存,而它調(diào)用的方法卻訪問了比這塊內(nèi)存更大的區(qū)域,出錯再在所難免。

同樣的情形還會發(fā)生在以下這些種情況中:

1) 應(yīng)用程序直接訪問類的公有變量,而該公有變量在新DLL中定義的位置發(fā)生了變化;
2) 應(yīng)用程序調(diào)用類的一個虛函數(shù),而新的類中,該虛函數(shù)的前面又增加了一個虛函數(shù);
3) 新類的后面增加了成員變量,并且新類的成員函數(shù)將訪問、修改這些變量;
4) 修改了新類的基類,基類的大小發(fā)生了變化;

等等,總言而之,一不小心,你的程序就會掉進地獄。通過對這些引起出錯的情況進行分析,會發(fā)現(xiàn)其實只有三點變化會引起出錯,因為這三點是使用這個DLL的應(yīng)用程序在編譯時就需要確定的內(nèi)容,它們分別是:
1) 類的大小;
2) 類成員的偏移地址;
3) 虛函數(shù)的順序。

要想做一個可升級的DLL,必需避免以上三個問題。所以以下三點用來使DLL遠離地獄。

1,不直接生成類的實例。對于類的大小,當我們定義一個類的實例,或使用new語句生成一個實例時,內(nèi)存的大小是在編譯時決定的。要使應(yīng)用程序不依賴于類的大小,只有一個辦法:應(yīng)用程序不生成類的實例,使用DLL中的函數(shù)來生成。把導(dǎo)出類的構(gòu)造函數(shù)定義為私有的(privated),在導(dǎo)出類中提供靜態(tài)(static)成員函數(shù)(如NewInstance())用來生成類的實例。因為NewInstance()函數(shù)在新的DLL中會被重新編譯,所以總能返回大小正確的實例內(nèi)存。

2,不直接訪問成員變量。應(yīng)用程序直接訪問類的成員變量時會用到該變量的偏移地址。所以避免偏移地址依賴的辦法就是不要直接訪問成員變量。把所有的成員變量的訪問控制都定義為保護型(protected)以上的級別,并為需要訪問的成員變量定義Get或Set方法。Get或Set方法在編譯新DLL時會被重新編譯,所以總能訪問到正確的變量位置。

3,忘了虛函數(shù)吧,就算有也不要讓應(yīng)用程序直接訪問它。因為類的構(gòu)造函數(shù)已經(jīng)是私有(privated)的了,所以應(yīng)用程序也不會去繼承這個類,也不會實現(xiàn)自己的多態(tài)。如果導(dǎo)出類的父類中有虛函數(shù),或設(shè)計需要(如類工場之類的框架),一定要把這些函數(shù)聲明為保護的(protected)以上的級別,并為應(yīng)用程序重新設(shè)計調(diào)用該慮函數(shù)的成員函數(shù)。這一點也類似于對成員變量的處理。

如果導(dǎo)出的類能遵循以上三點,那么以后對DLL的升級將可以認為是安全的。

如果對一個已經(jīng)存在的導(dǎo)出類的DLL進行維護,同樣也要注意:不要改動所有的成員變量,包括導(dǎo)出類的父類,無論定義的順序還是數(shù)量;不要動所有的虛函數(shù),無論順序還是數(shù)量。

總結(jié)起來,其實是一句話:導(dǎo)出類的DLL不要導(dǎo)出除了函數(shù)以外的任何內(nèi)容。聽起來是不是有點可笑呢!

事實上,建議你在發(fā)布導(dǎo)出類的DLL的時候,重新定義一個類的聲明,這個聲明可以不管原來的類里的成員變量之類的,只把接口函數(shù)列在類的聲明里,如下面的例子:
class ClassInterface
{
       privated:
              ClassInterface();
       public:
              static ClassInterface * NewInstance();
              int GetXXX();
              void SetXXX();
              void Function();
};

使用該DLL的應(yīng)用程序用上面的定義作為ClassInterface的頭文件,便不會有任何可能導(dǎo)致的安全問題。

DLL地獄問是歸根結(jié)底是因為DLL當初是作為函數(shù)級共享庫設(shè)計的,并不能真正提供一個類所必需的信息。類層上的程序復(fù)用只有Java和C#生成的類文件才能做到。 

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            国产精品人人做人人爽 | 国产日韩欧美在线播放| 免费成人激情视频| 欧美中文字幕视频在线观看| 一区二区福利| 一本久道久久综合中文字幕| 亚洲香蕉成视频在线观看| 一区二区三区国产精华| 亚洲午夜av| 欧美在线视频播放| 久久综合伊人77777| 欧美精品久久久久久久久老牛影院 | 国内自拍亚洲| 亚洲国产视频一区| 在线亚洲一区| 久久久一本精品99久久精品66| 老司机精品久久| 亚洲国产专区| 免费av成人在线| 亚洲国产精品一区二区三区| 久久精品99国产精品酒店日本| 亚洲日韩欧美视频一区| 亚洲视频免费观看| 久久久久综合一区二区三区| 欧美精品免费观看二区| 亚洲少妇最新在线视频| 中文日韩电影网站| 国产精品久久久久久久久久尿| 在线欧美日韩| 久久久噜噜噜久久中文字幕色伊伊| 欧美+亚洲+精品+三区| 亚洲夫妻自拍| 91久久在线| 亚洲日本中文字幕免费在线不卡| 久久精品综合网| 国产美女精品视频| 一区二区三区精品国产| 亚洲午夜电影在线观看| 亚洲高清av在线| 免费成人av在线| 精品二区视频| 久久久久在线观看| 亚洲国产日韩在线一区模特| 亚洲视频观看| 国内精品福利| 欧美jizzhd精品欧美巨大免费| 美女视频一区免费观看| 精品99视频| 欧美成人午夜77777| 亚洲欧洲日产国码二区| 久久国产一区二区三区| 在线欧美视频| 亚洲欧洲午夜| 国产日韩欧美精品综合| 狂野欧美一区| 欧美成人三级在线| 欧美一区二区三区婷婷月色 | 国产在线视频欧美| 欧美美女喷水视频| 一本色道久久综合亚洲精品婷婷| 一区二区三区日韩在线观看 | 久久精品首页| 午夜精品久久久久久久白皮肤| 亚洲经典在线看| 久久久国产视频91| 亚洲免费在线视频| 欧美视频日韩| 中文欧美字幕免费| 久久精品女人| 欧美日韩精品一本二本三本| 亚洲一区二区三区四区五区黄| 欧美激情精品| 亚洲在线播放电影| 午夜一区不卡| 毛片基地黄久久久久久天堂| 欧美日韩不卡一区| 亚洲小视频在线观看| 亚洲欧美激情视频| 欧美日韩精品| 欧美韩日一区二区| av成人免费在线| 欧美午夜精品久久久| 免费在线看成人av| 国产在线精品一区二区夜色| 在线亚洲伦理| 午夜精品在线看| 欧美日韩国产色站一区二区三区| 欧美成人精品福利| 亚洲第一精品夜夜躁人人爽| 久久久www成人免费无遮挡大片| 亚洲女与黑人做爰| 亚洲国产精品ⅴa在线观看| 国产精品一区亚洲| 免费在线观看精品| 性色av一区二区怡红| 日韩亚洲欧美一区二区三区| 国内精品美女在线观看| 欧美三级网址| 欧美另类女人| 欧美高清一区二区| 久久免费视频网| 久久国产手机看片| 国产精品99久久久久久久vr| 最新国产精品拍自在线播放| 久久蜜臀精品av| 欧美激情a∨在线视频播放| 国产一区二区三区在线观看免费 | 欧美韩日精品| 亚洲伦理在线观看| 久久精品一区蜜桃臀影院 | 日韩网站免费观看| 久久精品最新地址| 久久成人精品| 久久福利资源站| 久久这里只有精品视频首页| 久久久不卡网国产精品一区| 久久精品天堂| 亚洲福利视频专区| 在线亚洲精品| 久久亚洲一区二区| 一区二区三区在线免费播放| 激情欧美一区二区| av不卡在线| 欧美国产激情| 狂野欧美性猛交xxxx巴西| 欧美一区二区视频观看视频| 国产精品一级二级三级| 欧美日韩精品一区二区三区四区| 午夜免费在线观看精品视频| 午夜精品久久99蜜桃的功能介绍| 亚洲激情电影在线| 一区二区三区视频观看| 亚洲免费网站| 亚洲欧美日韩久久精品| 亚洲伊人色欲综合网| 欧美一区二区日韩一区二区| 毛片一区二区三区| 欧美伦理91i| 在线不卡免费欧美| 亚洲午夜伦理| 久久综合色天天久久综合图片| 久久精品夜色噜噜亚洲aⅴ| 美女久久一区| 亚洲社区在线观看| 亚洲精品影院在线观看| 午夜一区二区三区不卡视频| 久久久亚洲国产天美传媒修理工 | 亚洲激情电影在线| 亚洲毛片在线看| 欧美自拍丝袜亚洲| 国产精品系列在线| 亚洲视频在线二区| 亚洲毛片在线| 欧美激情四色 | 日韩亚洲不卡在线| 亚洲麻豆国产自偷在线| 亚洲精品乱码久久久久久蜜桃麻豆 | 老牛嫩草一区二区三区日本| 欧美成人精品一区| 欧美高清视频一区二区| 国产一区二区| 久久久久久久综合日本| 亚洲影院在线| 国产精品二区在线观看| 99视频在线精品国自产拍免费观看 | 国产精品欧美日韩| 欧美日本乱大交xxxxx| 亚洲第一搞黄网站| 亚洲激情不卡| 精品动漫3d一区二区三区| 亚洲国产高清视频| 久久亚洲精品一区| 狠狠综合久久| 日韩一本二本av| 欧美电影在线| 久久精品女人| 久久久久久一区二区三区| 久久久亚洲午夜电影| 欧美91精品| 在线成人h网| 欧美一区二区观看视频| 亚洲人成小说网站色在线| 亚洲一区二区三区高清| 欧美日本在线一区| 亚洲视频999| 午夜宅男久久久| 午夜亚洲精品| 欧美巨乳在线| 狠狠色狠狠色综合| 午夜精品久久久久| 国产午夜精品美女毛片视频| 小嫩嫩精品导航| 久久野战av| 最新亚洲电影| 久久免费视频在线| 久久精品一区二区| 久久精品卡一| 欧美一区二区三区免费视频| 亚洲午夜精品福利| 在线观看欧美一区|