日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Variant 与 内存泄露

發(fā)布時間:2023/12/19 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Variant 与 内存泄露 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

http://blog.chinaunix.net/uid-10386087-id-2959221.html


今天遇到一個內(nèi)存泄露的問題。是師兄檢測出來的。Variant類型在使用后要Clear否則會造成內(nèi)存泄露,為什么呢?

Google一下找到下面一篇文章,主要介紹了Com的內(nèi)存泄露,中間有對Variant的一些解釋吧。

1. 引用計數(shù)泄漏
由于C++的一些對象生命周期難以管理,在COM中加入了引用計數(shù),用來解決這個問題,引用計數(shù)是COM最重要的特性 之一。但諷刺的是,雖然很多COM組件是用C++寫的,但是在所有編程語言中,C++使用COM是最麻煩的,而且最容易產(chǎn)生引用計數(shù)的泄漏,從而最終造成 內(nèi)存泄漏。

引用計數(shù)泄漏一旦產(chǎn)生,比new了之后忘了delete還難以定位,因為一個對象可能被很多地方使用,根本就不知道到底是那個使用的地方在 AddRef之后沒有Release,只能知道對象泄漏了,但不知道是哪里導(dǎo)致泄漏。

因此在使用COM的時候,盡量使用智能指針,而且最好是所有使用COM的地方全部使用智能指針,這樣能在很大成都上防止產(chǎn)生COM對象的引用計數(shù)泄 漏。

然而使用了智能指針一定能解決問題嗎?也不一定,至少有以下兩種情況,使用了智能指針仍然會產(chǎn)生引用計數(shù)泄漏,而且比上面的情況更加難以找到原因:

對象循環(huán)引用導(dǎo)致引用計數(shù)泄漏
如果有兩個對象A和B,在A中使用了B,同時在B中使用了A,B對象中有一個智能指針指向A,A對象中有一 個智能指針指向B,這時候就會產(chǎn)生循環(huán)引用導(dǎo)致。因為A對象能被析構(gòu)的前提是B對象先析構(gòu),而B對象析構(gòu)的前提同樣是A對象先析構(gòu),這就成了一個死局,兩 個對象都無法析構(gòu),A和B都產(chǎn)生了內(nèi)存泄漏。

要想解決這種問題,一種方法是把這個循環(huán)的鏈打斷,在某個合適的地方把某一個對象中的智能指針顯示地把智能指針賦值為NULL,這樣循環(huán)的條件被打 破,兩個對象就都可以析構(gòu)了。另一種方法是使用弱引用,自動完成。但弱引用相對有點(diǎn)復(fù)雜,在本文中不作介紹,讀者可以自行在網(wǎng)上搜索相關(guān)資料。

不正確的智能指針使用方法導(dǎo)致引用計數(shù)泄漏
有時候使用了智能指針,并且也沒有循環(huán)引用,但是對象仍然有引用計數(shù)泄漏,是不是很困惑?對于 這種情況,有可能是因為使用智能指針不正確引起的。

我們有時候會這樣使用智能指針:

pUnknown->QueryInterface(__uuidof(IMyInterface), & spMyInterface);

spMyInterface變量是一個智能指針,在大多數(shù)情況下這樣使用不會有任何問題,尤其是使用了微軟的_com_ptr_t或CComPtr 等。但如果我們使用一些第三方的智能指針,例如Boost里的intrusive_ptr。我們知道,在_com_ptr_t和CComPtr中,重載 了&操作符,在&操作符中,會先釋放目前的引用計數(shù),然后返回一個指向指針的指針。這樣帶來的好處是使用&操作符的時候,都會先 釋放當(dāng)前的對象,不會造成內(nèi)存泄漏,壞處是這個智能指針可能無法放到一些STL的容器中,因為有一些STL的容器,在移動容器中的數(shù)據(jù)單元時,會用 到&操作符,這樣的結(jié)果是一旦移動,對象就被釋放了。Boost的智能指針,例如intrusive_ptr是沒有重載&操作符的,因此 可以放心地在STL容器中使用,但如果寫類似于QueryInterface(__uuidof(IMyInterface), & spMyInterface)就要特別小心了,例如像下面的連續(xù)兩次QueryInterface用法,就會產(chǎn)生引用計數(shù)泄漏:

boost::intrusive_ptr??? spMyInterface;

pUnknown->QueryInterface(__uuidof(IMyInterface), & spMyInterface);

pUnknown2->QueryInterface(__uuidof(IMyInterface), & spMyInterface);

因為第二次調(diào)用QueryInterface之前,spMyInterface并沒有Release,因此就有引用計數(shù)泄漏了。如果在某個循環(huán)中這 樣使用,則問題會更加嚴(yán)重。

要解決這類問題,有兩種方法。第一是同一個變量永遠(yuǎn)不要多次使用,在變量聲明周期中類似的操作只使用一次,如果有多次使用的需求,用別的變量來實(shí) 現(xiàn)。另一種方法是每次使用之前,都先顯示地把變量清空,釋放引用計數(shù),例如先spMyInterface,再調(diào)用QueryInterface。

2. 字符串(BSTR)泄漏
字符串泄漏容易被忽視,而且COM中使用的BSTR字符串,并不是用new或者malloc等來分配的,而 是用類似于::SysAllocString等API來分配的,要檢測是否有泄漏更加困難。

我們一般在調(diào)用某個類似于這樣的函數(shù)GetString([out] BSTR * str)的返回BSTR的指針的函數(shù)后,需要調(diào)用::SysFreeString把字符串釋放掉,和new/delete、malloc/free、 AddRef/Release類似。如果忘記調(diào)用::SysFreeString,就會產(chǎn)生內(nèi)存泄漏。

一般我們使用字符串類來自動釋放,例如使用CComBSTR,就可以這樣寫:

CComBSTR str;

GetString(&str);

str在析構(gòu)的時候會自動調(diào)用::SysFreeString把字符串釋放掉。

但如果看一下CComBSTR類的實(shí)現(xiàn),我們會發(fā)現(xiàn),這個類和Boost的intrusive_ptr類似,是沒有重載&操作符的,這就帶 來和intrusive_ptr一樣的問題,如果連續(xù)兩次以上使用這個字符串,就會產(chǎn)生內(nèi)存泄漏,例如字符串類我們有時候會這樣用:

CComBSTR str;

for(int I = 0;I < 100;I ++)

{

pInterface->GetString(&str);

// do something

}

這樣的后果是每調(diào)用一次,就會 產(chǎn)生一個內(nèi)存泄漏。因此一定要保證在字符串對象的生命周期中,只被使用一次,代碼改為這樣就不會有問題:

for(int I = 0;I < 100;I ++)

{

CComBSTR str;

pInterface->GetString(&str);

// do something

}

另外還有一種方法是使用_bstr_t的GetAddress函數(shù),這個函數(shù)返回的是 BSTR *,每次調(diào)用里面都會先釋放當(dāng)前的字符串,因此使用 _bstr_t屬于比較保險并且方便的選擇。不過遺憾的是在VC6中這個類并沒有實(shí)現(xiàn)GetAddress函數(shù),用起來可能會影響代碼的移植性。

3. VARIANT泄漏
這個情況和字符串泄漏類似,變量不再使用之后,應(yīng)該調(diào)用::VariantClear來釋放內(nèi)存,否則就可能會 產(chǎn)生內(nèi)存泄漏。

解決方法也和字符串類似,可以使用VARIANT的CComVariant,但這個類和CComBSTR也有一樣的問題,因此使用的時候也一樣要注 意,必須保證每個變量的生命周期中只使用一次。

另外有一個和_bstr_t類似的類:_variant_t,里面有一個GetAddress函數(shù)可以比較方便和安全的使用。具體的細(xì)節(jié)請參考這幾 個類的實(shí)現(xiàn)代碼,這里不多做介紹。

4. 總結(jié)
對于本文中提到的幾種內(nèi)存泄漏的原因,根源在于使用一個第三方的類的時候,其實(shí)并沒有真正理解這些類的實(shí)現(xiàn)原理,我們以為正確 地使用了,但其實(shí)用法并不對。因此在使用一個不是自己寫的第三方類的時候,不能直接拿過來就用,而是應(yīng)該花一點(diǎn)時間去仔細(xì)了解一下這個類,知道怎樣使用是 合理的,而怎樣使用是不正確的,把所有的隱患在編碼之前就解決掉,整個項目開發(fā)過程就會更加順利,產(chǎn)品質(zhì)量就會更高。

關(guān)于第三方類庫的使用,在本人另一篇博文《編碼原則十日談》中有提及,這里給出地址,供讀者參考。


總結(jié)

以上是生活随笔為你收集整理的Variant 与 内存泄露的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 成人免费视频毛片 | 桃花色综合影院 | 国产精久| 荒岛淫众女h文小说 | 少妇熟女高潮流白浆 | 中文字幕88 | 一个色亚洲 | 天堂中文资源在线 | 天堂素人 | av.www| 性日本xxx | 国产日韩精品在线 | 西欧free性满足hd老熟妇 | 污污网站在线播放 | 麻豆视频在线播放 | av免费在线播放 | 久久久久久伊人 | 91精品国产乱码久久久久久久久 | 亚洲精品一区二区三区影院忠贞 | 国产97视频 | 五月综合色婷婷 | 熟妇人妻av无码一区二区三区 | 国模无码大尺度一区二区三区 | 国产老妇视频 | 欧美激情在线免费 | 国产av电影一区二区三区 | 疯狂做受xxxx国产 | 久久久精品免费看 | 日本特黄一级大片 | 五月婷婷激情网 | 天海翼av | 九九一级片| 91秘密入口| 国产一区二区三区视频 | 在线你懂得 | 涩涩涩涩涩涩涩涩涩 | 国产男女无套免费网站 | 日韩在线免费观看视频 | 黄色高清免费 | 亚洲成av人影院 | 久久激情综合 | 91av爱爱| 欧美另类在线观看 | 天天cao在线 | 欧美久久久久久久久久久 | 超碰在线中文 | 操操操操操操操操操操 | 久久福利一区 | 久青草国产在线 | av黄色免费在线观看 | 日韩av在线资源 | 全黄一级裸体 | 操欧美女人 | 91午夜在线观看 | 精品国产乱码久久 | 少妇又紧又色又爽又刺激 | 中文字幕 自拍偷拍 | 啪啪导航 | 天堂婷婷| 久久午夜夜伦鲁鲁一区二区 | 日本精品视频一区 | 风流老熟女一区二区三区 | 性做久久久久久久免费看 | 一级黄色大片免费观看 | xxxxhd欧美 | 青青草官网 | 青青草视频黄 | 中文字幕 自拍 | a级片在线观看视频 | 天天操夜夜爽 | 欧美你懂得 | 日韩av二区 | 九九综合| 日韩黄色免费视频 | 99热这里只有精品3 成年人黄色网址 | 中文字幕 欧美 日韩 | 日本不卡一区在线观看 | 制服丝袜中文字幕在线 | 爱爱小视频免费看 | 国产黄色片av | 亚洲精品欧美 | 法国极品成人h版 | 日本亲近相奷中文字幕 | 日本三级中国三级99人妇网站 | xxxxhd欧美 | 四虎影院永久 | 淫五月| 日韩国产高清在线 | 日本免费三级网站 | 国产天天射 | 日韩精品免费一区二区三区竹菊 | 网红av在线 | 嫩草99| 污片免费在线观看 | 毛片国产精品 | 国产成人精品国内自产拍免费看 | 无码少妇一区二区 | 91福利视频导航 | 国产精选网站 |