释放参数BSTR使用误区以及隐藏的内存破坏和内存泄漏
PS:明天上午,非常郁悶,有很多簡(jiǎn)單基礎(chǔ)的問(wèn)題搞得我有些迷茫,哎,代碼幾天不寫(xiě)就忘。目前又不當(dāng)COO,還是得用心記代碼哦!
????BSTR應(yīng)用誤區(qū)以及隱藏的內(nèi)存損壞和內(nèi)存泄漏
????
????作者:magictong
????
????簡(jiǎn)介
????BSTR的數(shù)據(jù)結(jié)構(gòu)是什么模樣并非本文討論的問(wèn)題,但是卻是本文的基礎(chǔ)。在處理COM的跨平臺(tái)編程的問(wèn)題時(shí),需要定義一種通用的字符串類型,它就這樣被發(fā)明白,而且它的結(jié)構(gòu)很輕易匹配到不同的編程環(huán)境中,對(duì)于C++程序員來(lái)講,要記著的最基本的一點(diǎn)就是分配BSTR結(jié)構(gòu)時(shí),并非簡(jiǎn)單的調(diào)用new、malloc就能夠?qū)崿F(xiàn)的,而且大部分的字符串相關(guān)的API和C庫(kù)函數(shù)也是不能用于處理BSTR的,其實(shí)這也是應(yīng)用BSTR的誤區(qū)之一,在C++里面,BSTR被簡(jiǎn)單的define為wchar_t*,這也是輕易引發(fā)誤解的原因之一。
????明天注意討論一下BSTR作為函數(shù)的參數(shù)、返回值時(shí),調(diào)用者和被調(diào)用者操作BSTR時(shí)扮演的不同角色問(wèn)題。首先需要注意的時(shí),在必須應(yīng)用BSTR時(shí)盡量應(yīng)用BSTR的包裝類CComBSTR,它會(huì)給你額定實(shí)現(xiàn)一些資源的管理工作,令你省力不少,犯錯(cuò)的可能性也就大大降低了。
????像一個(gè)很簡(jiǎn)單自然的用法:BSTR?bstrInfo?=?L””,實(shí)際上是錯(cuò)誤的(當(dāng)然如果你說(shuō)我當(dāng)前就把bstrInfo完全當(dāng)成wchar_t*來(lái)應(yīng)用,那我無(wú)話可說(shuō))。對(duì)于一個(gè)BSTR變量來(lái)講,它只多是NULL或者正確分配的BSTR指針。
????
????BSTR當(dāng)成參數(shù)和返回應(yīng)用的基本約定
????1、[in\out]參數(shù)
????譬如函數(shù):void?GetChangBSTR(BSTR*?pbstrTitle),在GetChangBSTR函數(shù)外部需要先讀取pbstrTitle的值應(yīng)用,然后改變pbstrTitle的值。
????這類情況下被調(diào)用者(也就是GetChangBSTR)在給pbstrTitle賦新值前,需要先釋放pbstrTitle里面本來(lái)的值,然后再給pbstrTitle分配上新的值。
????而調(diào)用者(也就是調(diào)用GetChangBSTR的函數(shù)),在傳參之前需要先給pbstrTitle賦值上正確的值,調(diào)用結(jié)束之后還需要再釋放pbstrTitle的值。
????
????2、[in]參數(shù)
????譬如函數(shù):void?PutText(BSTR?bstrText),在PutText外部?jī)H需讀取bstrText的值。
????這類情況下被調(diào)用者可以隨意讀取bstrText的值,不需要做其它操作。
????而調(diào)用者,在傳參之前需要先給bstrText賦上正確的值,調(diào)用結(jié)束后需要釋放bstrText的值。
????
????3、[out]參數(shù)
????譬如函數(shù):void?GetText(BSTR*?pbstrText),在GetText外部直接給pbstrText賦值。
????這類情況下被調(diào)用者直接給pbstrText賦值便可,不需要做其它操作。
????而調(diào)用者,在傳參之前不能給pbstrText賦值,調(diào)用結(jié)束后需要釋放pbstrText的值。
????
????4、返回參數(shù)
????譬如函數(shù):BSTR?GetText(),在GetText外部會(huì)返回一個(gè)BSTR出來(lái)。調(diào)用者直接返回一個(gè)有效的BSTR便可,而調(diào)用者需要釋放這個(gè)返回的BSTR。
????
????BSTR當(dāng)成參數(shù)和返回應(yīng)用的誤區(qū)
????1、[in\out]參數(shù)
????這類情況下,被調(diào)用者如果沒(méi)有給參數(shù)賦值,不要釋放原始值,因?yàn)楦鶕?jù)約定調(diào)用者還會(huì)釋放一次,這樣會(huì)造成多次釋放,可能致使內(nèi)存損壞。
????void?GetChangBSTR(/*[in\out]?*/BSTR*?pbstrTitle)
????{
????//?using?the?bs?here
????DoSomething(*pbstrTitle);
?????
????if?(...)
????{
????::SysReAllocString(*pbstrTitle,?_T("Tecnet"));
????}
????else
????{
????::SysFreeString(*pbstrTitle);?//?這里的做法是錯(cuò)誤的。
????}
????return;
????}
????
????2、[in]參數(shù)
????被調(diào)用者不要對(duì)參數(shù)停止釋放操作,原因和上面相同,調(diào)用者還會(huì)重復(fù)釋放一次,可能致使內(nèi)存損壞。
????void?PutText(/*[in]?*/BSTR?bstrText)
????{
????//?using?the?bs?here
????DoSomething(bstrText);
????::SysFreeString(bstrText);?//?這里的做法是錯(cuò)誤的。
????
????return;
????}
????
????3、[out]參數(shù)
????如果調(diào)用者在傳參之前給參數(shù)賦值,參數(shù)傳遞給被調(diào)用者之后,在改變值之前是沒(méi)有釋放操作的,也就是說(shuō)會(huì)有內(nèi)存泄漏。
????void?GetText(/*[out]?*/BSTR*?pbstrText)
????{
????::SysAllocString(*pbstrText,?_T("Tecnet"));
????return;
????}
????//?use?GetText
????BSTR?bstrText;
????::SysAllocString(bstrText,?_T("qq"));
????GetText(&bstrText);
????::SysFreeString(bstrText);?//?很可憐,這里實(shí)際上只釋放了一次
????
????4、返回參數(shù)
????被調(diào)用者不要釋放(不管是直接還是直接致使的)返回給調(diào)用者的BSTR,因?yàn)檎{(diào)用者會(huì)釋放。
????BSTR?GetText()
????{
????BSTR?bstrText?=?::SysAllocString(bstrText,?_T("Tecnet"));
????::SysFreeString(bstrText);?//?這里釋放就喜劇了
????return?bstrText;
????}
????//?use?GetText
????BSTR?bstrText?=?GetText(&bstrText);
????//?use?bstrText
????DoSome(bstrText);?//?bstrText已經(jīng)被釋放,應(yīng)用是有問(wèn)題的
每日一道理一個(gè)安靜的夜晚,我獨(dú)自一人,有些空虛,有些凄涼。坐在星空下,抬頭仰望美麗天空,感覺(jué)真實(shí)卻由虛幻,閃閃爍爍,似乎看來(lái)還有些跳動(dòng)。美的一切總在瞬間,如同“海市蜃樓”般,也只是剎那間的一閃而過(guò),當(dāng)天空變得明亮,而這星星也早已一同退去……
????::SysFreeString(bstrText);?//?這就不僅僅是重復(fù)釋放的問(wèn)題了
????
????BSTR在類里面應(yīng)用的誤區(qū)
????1、我想把某個(gè)[in]參數(shù)BSTR保存到某個(gè)類成員變量
????這類情況下,直接賦值是不行的,因?yàn)楸砻嬲{(diào)用者會(huì)釋放這個(gè)BSTR參數(shù),因此要保存的話,需要類函數(shù)自己重新申請(qǐng)一個(gè)新的BSTR。
????void?CSomeClass::SetText(BSTR?bs)
????{
????//?m_bstrText是CSomeClass的成員變量
????m_bstrText?=?bs;?//?錯(cuò)誤做法
????m_bstrText?=?::SysReAllocString(bs);?//?正確做法
????}
????
????2、我想傳出一個(gè)類的BSTR成員變量
????同樣的道理,因?yàn)楸砻婵赡茉谀硞€(gè)時(shí)間釋放傳出的BSTR變量,因此要防止類成員變量被無(wú)辜釋放,需要生成一個(gè)有效的拷貝,再傳出。
????void?CSomeClass::GetText(BSTR&?bs)
????{
????//?m_bstrText是CSomeClass的成員變量
????bs?=?m_bstrText;?//?錯(cuò)誤做法
????bs?=?::SysAllocString(m_bstrText);?//?正確做法
????}
????
????BSTR的封裝類CComBSTR
????微軟發(fā)明我們應(yīng)用BSTR有上面的各種不爽,因此決議對(duì)其停止封裝,很貼心吧!嗯,確實(shí)貼心,其中比擬好的一個(gè)封裝就是CComBSTR(很多項(xiàng)目組可能有自己的BSTR封裝,但是其實(shí)都是迥然不同的),這個(gè)封裝類確實(shí)很好用(雖然沒(méi)有供給CString那么多牛皮的功能),應(yīng)用很方便,但是,如果我們錯(cuò)誤應(yīng)用也會(huì)發(fā)生噩夢(mèng),而且錯(cuò)誤很難查找,我們來(lái)點(diǎn)評(píng)幾個(gè)(注意:下面的內(nèi)容需要對(duì)CComBSTR封裝的基本原理和供給接口有必定了解,但這些并非本文要討論的內(nèi)容,另外一個(gè)封裝類是_bstr_t,它是用引用計(jì)數(shù)來(lái)管理的,實(shí)現(xiàn)比CComBSTR復(fù)雜很多,個(gè)人不太建議應(yīng)用_bstr_t)。
????1、被調(diào)用者違背out參數(shù)應(yīng)用約定
????void?GetText(/*[out]*/BSTR&?bstrText)
????{
????CComBSTR?bstrT(_T("qqpcmgr"));
????//?錯(cuò)誤:bstrT會(huì)被自動(dòng)釋放,違背了out參數(shù)的應(yīng)用約定
????bstrText?=?(BSTR)bstrT;
????return;
????
????//
????//?正確的做法,一般來(lái)講Detach是效率更好的方法
????//?但是如果bstrT本身是一個(gè)類成員變量,可能要用Copy
????bstrText?=?bstrT.Copy();
????????bstrText?=?bstrT.Detach();
????return;
????}
????
????2、調(diào)用者違背out參數(shù)應(yīng)用約定
????void?GetText(/*[out]*/BSTR&?bstrText)
????{
????//?……
????}
????//?use?GetText
????CComBSTR?bstrText(L"qq");
????//?內(nèi)存泄漏,調(diào)用GetText前要先清空bstrText
????//?bstrText.Empty();
????GetText(bstrText);
????
????3、看一個(gè)費(fèi)解一點(diǎn)的
????void?GetText(/*[out]*/BSTR&?bstrText)
????{
????//?……
????}
????//?use?GetText
????CComBSTR?bstrText;
????BSTR?bstrInfo?=?NULL;
????GetText(bstrInfo);
????//?如果后面沒(méi)有表現(xiàn)釋放bstrInfo
????//?這里就會(huì)有內(nèi)存泄漏,這類混用也是比擬危險(xiǎn)的
????bstrText?=?bstrInfo;
????//?如果你想CComBSTR接管一個(gè)BSTR,可以應(yīng)用
????//?bstrText.Attach(bstrInfo);
????
????4、重復(fù)釋放,造成內(nèi)存損壞
????{
????CComBSTR?bstrText(L"Tencent");
????//?因?yàn)?/span>CComBSTR重載了operator?BSTR操作,因此這里是支持的
????::SysFreeString(bstrText);?//?錯(cuò)誤做法,如果你確實(shí)想釋放,可以調(diào)用Empty
????}
????//?超越bstrText范圍,bstrText會(huì)被自動(dòng)釋放,可能致使內(nèi)存損壞
????//?……
????
????參考文獻(xiàn)
????[1]?BSTR?https://zh.wikipedia.org/zh-cn/BSTR
????[2]?BSTR_INSIDE?http://wenku.baidu.com/view/d577a1c5d5bbfd0a795673b2.html
????
文章結(jié)束給大家分享下程序員的一些笑話語(yǔ)錄: 現(xiàn)在社會(huì)太數(shù)字化了,所以最好是有一個(gè)集很多功能于一身的設(shè)備!
--------------------------------- 原創(chuàng)文章 By
釋放和參數(shù)
---------------------------------
轉(zhuǎn)載于:https://www.cnblogs.com/xinyuyuanm/archive/2013/05/30/3108990.html
總結(jié)
以上是生活随笔為你收集整理的释放参数BSTR使用误区以及隐藏的内存破坏和内存泄漏的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: inverted index 反向索引
- 下一篇: truenas快速设置第二弹(nextc