青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
RTY 實踐出真知
posts - 319, comments - 22, trackbacks - 0, articles - 11
C++博客
::
首頁
::
新隨筆
::
聯系
::
聚合
::
管理
DLL導出類的問題
Posted on 2011-08-10 07:23
RTY
閱讀(844)
評論(0)
編輯
收藏
引用
所屬分類:
C/C++
、
Windows
DLL導出類的問題
http://www.diybl.com/course/3_program/c++/cppjs/200833/102641.html
DLL動態鏈接庫是程序復用的重要方式,DLL可以導出函數,使函數被多個程序復用,DLL中的函數實現可以被修改而無需重新編譯和連接使用該DLL的應用程序。作為一名面向對象的程序員,希望DLL可以導出類,以便在類的層次上實現復用。所幸的是,DLL確實也可以導出類。
然而事實卻沒這么簡單,導出類的DLL在維護和修改時有很多地方必需很小心,增加成員變量、修改導出類的基類等操作都可能導致意想不到的后果,也許
用戶
更新了最新版本的DLL庫后,應用程序就再也不能
工作
了。這就是著名的DLL Hell(DLL地獄)問題。
DLL地獄問題是怎么產生的呢?看下面的例子,假設DLL有一個導出類ClassD1:
class ClassD
{
public:
int GetInt();
private:
int m_i;
};
int ClassD::GetInt()
{
return m_i;
}
應用程序使用現在的代碼來使用這個類:
ClassD d;
printf(“%d”, d.GetInt());
程序進行正正常,沒有什么問題。后來DLL需要升級,對ClassD進行了修改,增加了一個成員變量,如下:
class ClassD // 修改后
{
public:
int GetInt();
private:
int m_i2;
int m_i;
};
把新的DLL編譯連接完成后,復制到應用程序目錄,這個倒楣的應用程序調用GetInt方法恐怕再也無法得正確的值了。事實上它還算幸運的,如果GetInt的實現改成如下這樣,那么它馬上就要出錯退出了。
int ClassD::GetInt() // 修改后
{
return m_i++;
}
這樣的事情,稱它是個地獄(Hell)一點也不夸張。為什么會出錯呢?我們要先從類實例的創建開始,看看使用一個類的工作過程。
首先,程序語句“ClassD d;”為這個類申請一塊內存。這塊內存保存該類的所有成員變量,以及虛函數表。內存的大小由類的聲明決定,在應用程序編譯時就已經確定。
然后,當調用“d.GetInt()”時,把申請的這一塊內存做為this指針傳給GetInt函數,GetInt函數從this指向的位置開始,加上m_i應有的偏移量,計算m_i所在的內存位置,并從該位置取數據返回。m_i相對this的偏移量是由m_i在類中定義的位置決定的,定義在前的成員變量在內存中也更靠前。這個偏移量在DLL編譯時確定。
當ClassD的定義改為修改后的狀態時,有些東西變了。
第一個變的是內存的大小。因為修改后的ClassD多了一個成員變量,所以內存也變大了。然而這一點應用程序并不知道。
第二個變的是m_i的偏移地址。因為在m_i之前定義了一個m_i2,m_i的實現偏移地址實際已經靠后了。所以d.GetInt()訪問的將是原來m_i后面的那個位置,而這個位置已經超出原來那塊內存的后部范圍了。
很顯然,在更換了DLL后,應用程序還按原來的大小申請了一塊內存,而它調用的方法卻訪問了比這塊內存更大的區域,出錯再在所難免。
同樣的情形還會發生在以下這些種情況中:
1)
應用程序直接訪問類的公有變量,而該公有變量在新DLL中定義的位置發生了變化;
2)
應用程序調用類的一個虛函數,而新的類中,該虛函數的前面又增加了一個虛函數;
3)
新類的后面增加了成員變量,并且新類的成員函數將訪問、修改這些變量;
4)
修改了新類的基類,基類的大小發生了變化;
等等,總言而之,一不小心,你的程序就會掉進地獄。通過對這些引起出錯的情況進行分析,會
發現
其實只有三點變化會引起出錯,因為這三點是使用這個DLL的應用程序在編譯時就需要確定的內容,它們分別是:
1)
類的大小;
2)
類成員的偏移地址;
3)
虛函數的順序。
要想做一個可升級的DLL,必需避免以上三個問題。所以以下三點用來使DLL遠離地獄。
1,不直接生成類的實例。對于類的大小,當我們定義一個類的實例,或使用new語句生成一個實例時,內存的大小是在編譯時決定的。要使應用程序不依賴于類的大小,只有一個辦法:應用程序不生成類的實例,使用DLL中的函數來生成。把導出類的構造函數定義為私有的(privated),在導出類中提供靜態(static)成員函數(如NewInstance())用來生成類的實例。因為NewInstance()函數在新的DLL中會被重新編譯,所以總能返回大小正確的實例內存。
2,不直接訪問成員變量。應用程序直接訪問類的成員變量時會用到該變量的偏移地址。所以避免偏移地址依賴的辦法就是不要直接訪問成員變量。把所有的成員變量的訪問控制都定義為保護型(protected)以上的級別,并為需要訪問的成員變量定義Get或Set方法。Get或Set方法在編譯新DLL時會被重新編譯,所以總能訪問到正確的變量位置。
3,忘了虛函數吧,就算有也不要讓應用程序直接訪問它。因為類的構造函數已經是私有(privated)的了,所以應用程序也不會去繼承這個類,也不會實現自己的多態。如果導出類的父類中有虛函數,或設計需要(如類工場之類的框架),一定要把這些函數聲明為保護的(protected)以上的級別,并為應用程序重新設計調用該慮函數的成員函數。這一點也類似于對成員變量的處理。
如果導出的類能遵循以上三點,那么以后對DLL的升級將可以認為是安全的。
如果對一個已經存在的導出類的DLL進行維護,同樣也要注意:不要改動所有的成員變量,包括導出類的父類,無論定義的順序還是數量;不要動所有的虛函數,無論順序還是數量。
總結起來,其實是一句話:導出類的DLL不要導出除了函數以外的任何內容。聽起來是不是有點可笑呢!
事實上,建議你在發布導出類的DLL的時候,重新定義一個類的聲明,這個聲明可以不管原來的類里的成員變量之類的,只把接口函數列在類的聲明里,如下面的例子:
class ClassInterface
{
privated:
ClassInterface();
public:
static ClassInterface * NewInstance();
int GetXXX();
void SetXXX();
void Function();
};
使用該DLL的應用程序用上面的定義作為ClassInterface的頭文件,便不會有任何可能導致的安全問題。
DLL地獄問是歸根結底是因為DLL當初是作為函數級共享庫設計的,并不能真正提供一個類所必需的信息。類層上的程序復用只有Java和C#生成的類文件才能做到。
只有注冊用戶
登錄
后才能發表評論。
相關文章:
Dynamic Library Design Guidelines (Xcode)
Qt internal error: qt_menu.nib could not be loaded.
Cocoa讀取和寫入plist文件
什么叫IOC(編程術語)
otool 與dylib
找不到 dirent.h 文件
vc調試窗口表達式格式化資料
Context Operator (C/C++ Language Expressions)
Managed Expressions in C++ (VC 2010 調試)
Find path of an application
網站導航:
博客園
IT新聞
BlogJava
博問
Chat2DB
管理
Powered by:
C++博客
Copyright © RTY
日歷
<
2011年4月
>
日
一
二
三
四
五
六
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
1
2
3
4
5
6
7
常用鏈接
我的隨筆
我的評論
我參與的隨筆
留言簿
(12)
給我留言
查看公開留言
查看私人留言
隨筆分類
(538)
C/C++(70)
CSS(41)
JavaScript(6)
Linux(7)
Lua專題(3)
Mac os(34)
Python(33)
QML(21)
Qt(65)
TBB(4)
Windows(38)
XML
編程常識(37)
軟件(38)
數據庫
需要注意的(14)
質量保障(14)
轉載隨筆(113)
隨筆檔案
(319)
2013年3月 (2)
2013年2月 (5)
2013年1月 (4)
2012年12月 (2)
2012年11月 (7)
2012年10月 (1)
2012年9月 (1)
2012年7月 (1)
2012年6月 (2)
2012年5月 (5)
2012年4月 (15)
2012年3月 (13)
2012年2月 (5)
2012年1月 (1)
2011年12月 (1)
2011年11月 (5)
2011年10月 (5)
2011年9月 (26)
2011年8月 (51)
2011年7月 (23)
2011年6月 (22)
2011年5月 (82)
2011年4月 (38)
2010年12月 (2)
文章分類
(11)
C/C++文章收集
Linux(3)
QT相關資料收集(8)
文章檔案
(11)
2010年12月 (11)
官方教程
知識共享鏈接
搜索
最新評論
1.?re: OSGi開發起步
評論內容較長,點擊標題查看
--M.I
2.?re: iOS中plist的創建,數據寫入與讀取
評論內容較長,點擊標題查看
--泰國
3.?re: Windows 7使用技巧:在當前路徑下打開命令行(cmd)命令窗口
給力啊
--gy
4.?re: codesign CSSMERR_TP_NOT_TRUSTED
你好,能告訴我你QQ么,我遇到了這問題,但是安裝了證書后還是這樣,能幫我看看么
--潮
5.?re: Windows 7使用技巧:在當前路徑下打開命令行(cmd)命令窗口
好用
--xxoo
閱讀排行榜
1.?找不到 dirent.h 文件(9723)
2.?實現Qt日志功能并輸出到文件(qDebug\qWarning\ qCritical\qFatal)(9337)
3.?VirtualBox虛擬機安裝Mac OS X Lion(8965)
4.?Windows 7使用技巧:在當前路徑下打開命令行(cmd)命令窗口(8156)
5.?iOS中plist的創建,數據寫入與讀取(7747)
評論排行榜
1.?字符集編碼與 C/C++ 源文件字符編譯亂彈(收集轉載)(4)
2.?Windows 7使用技巧:在當前路徑下打開命令行(cmd)命令窗口(4)
3.?Intel Parallel Studio XE 2011(3)
4.?QML與c++交互學習筆記(八) qt c++直接調用QML中的函數, 直接設置屬性 (2)
5.?VirtualBox虛擬機安裝Mac OS X Lion(2)
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
国产精品成人久久久久
|
国产精品久久91
|
在线观看亚洲视频
|
免费看精品久久片
|
久久久天天操
|
亚洲精品一二
|
中文亚洲欧美
|
国产亚洲精品久久久
|
另类酷文…触手系列精品集v1小说
|
久久精品1区
|
亚洲精品一区在线
|
一本色道久久综合精品竹菊
|
国产精品人人做人人爽人人添
|
先锋影音一区二区三区
|
欧美专区中文字幕
|
亚洲国产欧美在线人成
|
日韩一级欧洲
|
国产午夜久久
|
亚洲欧洲精品成人久久奇米网
|
亚洲精品在线视频
|
国产精品久久久999
|
久久久久久久久久久一区
|
蜜桃久久av
|
亚洲欧美不卡
|
久久一区二区精品
|
亚洲——在线
|
久久―日本道色综合久久
|
在线性视频日韩欧美
|
欧美在线影院在线视频
|
99视频一区二区
|
欧美一区免费
|
一区二区三区鲁丝不卡
|
久久成人精品
|
亚洲一区免费
|
欧美精品久久久久久久免费观看
|
99精品国产在热久久下载
|
国产精品自拍在线
|
最新成人av在线
|
韩国一区二区三区在线观看
|
一本久久青青
|
亚洲三级视频
|
久久精品一本久久99精品
|
亚洲欧美视频在线观看
|
欧美二区在线播放
|
欧美1级日本1级
|
国产日韩欧美三区
|
一本色道久久综合狠狠躁篇的优点
|
在线观看视频免费一区二区三区
|
亚洲神马久久
|
亚洲一区二区在线看
|
欧美激情一区三区
|
黄色另类av
|
久久全球大尺度高清视频
|
欧美在线观看网站
|
夜久久久久久
|
亚洲精品视频二区
|
老司机免费视频久久
|
欧美在线视频免费
|
国产精品亚洲成人
|
一本大道久久a久久精品综合
|
亚洲国产婷婷综合在线精品
|
久久精品亚洲精品
|
国产精品久久久久久久久搜平片
|
欧美午夜精品一区二区三区
|
亚洲国产成人在线
|
亚洲国产影院
|
欧美成人精品福利
|
亚洲欧洲一区二区三区
|
99pao成人国产永久免费视频
|
欧美成人视屏
|
亚洲日本va午夜在线电影
|
亚洲精品乱码久久久久久蜜桃麻豆
|
亚洲国产片色
|
一区二区三区免费在线观看
|
欧美日韩国产一区二区
|
99在线观看免费视频精品观看
|
一本色道久久
|
国产精品久久久久久久免费软件
|
一区二区三区四区五区视频
|
亚洲欧美日韩直播
|
国产一区日韩二区欧美三区
|
久久成人久久爱
|
欧美国产一区视频在线观看
|
亚洲毛片在线免费观看
|
欧美日韩日本国产亚洲在线
|
亚洲性视频网站
|
久久蜜桃香蕉精品一区二区三区
|
亚洲二区免费
|
欧美日韩综合久久
|
欧美一区午夜精品
|
亚洲国产精品精华液2区45
|
一区二区三区四区蜜桃
|
国产毛片一区
|
欧美成人中文字幕在线
|
亚洲一二三区在线
|
麻豆精品精华液
|
99国产精品
|
国产亚洲成年网址在线观看
|
免费看的黄色欧美网站
|
aa级大片欧美三级
|
免费在线欧美视频
|
亚洲一区久久久
|
影音先锋亚洲一区
|
欧美天堂亚洲电影院在线播放
|
欧美在线观看天堂一区二区三区
|
亚洲二区免费
|
久久精视频免费在线久久完整在线看
|
亚洲黄色影片
|
国产精品人人做人人爽
|
免费一区视频
|
欧美亚洲综合网
|
99国产精品99久久久久久粉嫩
|
久久久久久穴
|
亚洲欧洲av一区二区
|
亚洲国产高清视频
|
国产日韩欧美制服另类
|
欧美精品一区二区三区视频
|
久久精品欧美日韩精品
|
亚洲资源在线观看
|
亚洲精品日韩在线
|
免费欧美高清视频
|
久久国产主播精品
|
午夜日本精品
|
亚洲男人天堂2024
|
日韩午夜在线播放
|
91久久精品国产
|
狠狠色狠狠色综合
|
国产日产亚洲精品
|
国产精品国产
|
欧美理论视频
|
欧美人与性动交cc0o
|
欧美xx69
|
男女av一区三区二区色多
|
亚洲午夜性刺激影院
|
亚洲精品在线电影
|
亚洲精品欧洲精品
|
亚洲黄色尤物视频
|
亚洲国产高清视频
|
欧美国产乱视频
|
欧美a级一区二区
|
欧美高清视频一区二区三区在线观看
|
久久久久久婷
|
久久亚洲国产成人
|
免费视频久久
|
欧美jizz19hd性欧美
|
母乳一区在线观看
|
免费国产一区二区
|
欧美国产欧美亚洲国产日韩mv天天看完整
|
欧美在线电影
|
久久国产主播
|
久久久高清一区二区三区
|
久久精品视频在线
|
久久躁日日躁aaaaxxxx
|
久久综合影音
|
欧美福利视频一区
|
亚洲国产成人精品久久
|
亚洲激情图片小说视频
|
99天天综合性
|
亚洲影院在线
|
久久久91精品国产一区二区精品
|
欧美影院久久久
|
久久久亚洲人
|
欧美精品三级
|
国产精品亚洲一区二区三区在线
|
国产欧美一区二区三区沐欲
|
国内精品久久久
|
亚洲日本一区二区三区
|
亚洲一区视频在线
|
久久琪琪电影院
|
亚洲黄页视频免费观看
|
亚洲午夜激情免费视频
|
久久久久久久尹人综合网亚洲
|
欧美成人中文字幕
|
国产精品国产三级国产普通话蜜臀
|
免费成人你懂的
|
欧美体内谢she精2性欧美
|
国产毛片久久
|
亚洲人体1000
|
欧美在线首页
|
亚洲激情在线播放
|
亚洲欧美日韩另类
|
欧美成人黄色小视频
|
国产精品一区一区
|
亚洲国产成人不卡
|
欧美伊人久久久久久午夜久久久久
|
日韩亚洲视频在线
|
久久国产精品亚洲77777
|
91久久国产精品91久久性色
|
午夜精品久久
|
欧美日韩国产精品专区
|
在线国产亚洲欧美
|
先锋影音国产一区
|
亚洲高清免费
|
久久国产精品一区二区三区四区
|
欧美精品日韩三级
|
一区二区在线观看视频在线观看
|
韩国av一区二区三区
|
亚洲一本大道在线
|
亚洲电影一级黄
|
欧美中文字幕在线
|