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

今天遇到一個(gè)比較奇怪的crash問題,這里記錄下。這個(gè)crash是由QA設(shè)置了一些不合理的參數(shù)引起的,還好QA當(dāng)時(shí)保存了Dump文件,讓我們可以慢慢分析,從而找出代碼中隱藏的問題。
    
這里先簡單介紹下ATL/WTL里字符串的設(shè)計(jì):
(1)每個(gè)CString都有自己的串頭(內(nèi)含引用計(jì)數(shù),數(shù)據(jù)長度,已分配內(nèi)存長度),緊接著后面是真正的數(shù)據(jù)。
因?yàn)槭腔谝糜?jì)數(shù),所以相同的多個(gè)CString可以共享同一份數(shù)據(jù)。
struct CStringData
{
    long nRefs;     // reference count
    int nDataLength;
    int nAllocLength;
    // TCHAR data[nAllocLength]

    TCHAR* data()
    { return (TCHAR*)(this + 1); }
};


(2)每個(gè)未初始化CString都會(huì)指向同一固定的全局?jǐn)?shù)據(jù),內(nèi)部引用計(jì)數(shù)、數(shù)據(jù)長度、已分配內(nèi)存長度、內(nèi)容分別為-1,0,0,0
// Globals

// For an empty string, m_pchData will point here
// (note: avoids special case of checking for NULL m_pchData)
// empty string data (and locked)
_declspec(selectany) int rgInitData[] = { -1, 0, 0, 0 };
_declspec(selectany) CStringData* _atltmpDataNil = (CStringData*)&rgInitData;
_declspec(selectany) LPCTSTR _atltmpPchNil = (LPCTSTR)(((BYTE*)&rgInitData) + sizeof(CStringData));

inline CString::CString()
{
Init();
}
inline void CString::Init()
{ m_pchData = _GetEmptyString().m_pchData; }

static const CString& __stdcall _GetEmptyString()
{
return *(CString*)&_atltmpPchNil;
}

(3)字符串析構(gòu)時(shí)會(huì)檢測是否已經(jīng)分配內(nèi)存,是否其他沒有人用(引用計(jì)數(shù)小于0),都滿足后才會(huì)最終釋放內(nèi)存。
inline CString::~CString()
//  free any attached data
{
    if (GetData() != _atltmpDataNil)
    {
        if (InterlockedDecrement(&GetData()->nRefs) <= 0)
            delete[] (BYTE*)GetData();
    }
}

 用Windbg打開Dump文件,輸入!analyze -v 讓它自動(dòng)分析Crash時(shí)的情況,最終發(fā)現(xiàn)Crash在ATL/WTL字符串的析構(gòu)函數(shù)~CString()里的delete語句, 然后我們通過分析傳入?yún)?shù),發(fā)現(xiàn)外部傳入的是一個(gè)沒有初始化的CString,既然是沒有初始化的CString,那應(yīng)該都是指向初始字符串的固定內(nèi)存,也就不會(huì)滿足條件 if (GetData() != _atltmpDataNil),為什么會(huì)跑到里面去呢?

這里關(guān)鍵原因就是這個(gè)CString是跨模塊傳遞過來的,比如你DLL里有個(gè)導(dǎo)出函數(shù)void SetValue(CString strValue), 然后你外部Exe傳遞一個(gè)未出始化的字符串CString str; SetValue(str); 這時(shí)就會(huì)Crash。根本原因是因?yàn)閭魅氲淖址窃贓xe里構(gòu)造,但是在DLL里析構(gòu),Exe里的未初始化str指向的是Exe模塊自己的全局初始值Exe!_atltmpDataNil, 而DLL內(nèi)CString的全局初始值是Dll自己的Dll!_atltmpDataNil, 兩者比較當(dāng)然不相等,而后面的if (InterlockedDecrement(&GetData()->nRefs) <= 0)又會(huì)把引用計(jì)數(shù)從-1改成-2, 接下來就會(huì)試圖delete這塊不是new出來的全局內(nèi)存,當(dāng)然會(huì)Crash了。

這個(gè)Bug一直沒有發(fā)現(xiàn)的原因是QA一直設(shè)置的都是有效參數(shù),也就不會(huì)引起傳入未初始化的CString的情況,但這次意外卻暴露了我們代碼中隱藏的問題。

知道了原因,接下來就是如何改了?方法很多,可以用傳引用的方式CString&;也可以傳C方式的字符串LPCTSTR;也可以還是傳CString, 但是在傳之前先做下長度判斷,以確保已經(jīng)出始化。

另外提醒下如果要在模塊(DLL)之間傳遞內(nèi)存,要確保C/C++運(yùn)行庫要用DLL的方式(MD), 這樣跨模塊new和delete時(shí)他們會(huì)共享同一個(gè)內(nèi)存堆,不同模塊之間相互new和delete才不會(huì)有問題。

測試工程: DllStringTest
posted on 2012-07-13 21:27 Richard Wei 閱讀(3917) 評(píng)論(4)  編輯 收藏 引用 所屬分類: windbg

FeedBack:
# re: 跨模塊傳參數(shù)的教訓(xùn)
2012-07-14 00:42 | 10年碼農(nóng)
經(jīng)典問題了,MD雖然可以解決,但個(gè)人感覺,還是應(yīng)該養(yǎng)成哪里分配哪里釋放的好??鏒LL釋放總不是很好。。  回復(fù)  更多評(píng)論
  
# re: 跨模塊傳參數(shù)的教訓(xùn)[未登錄]
2012-07-14 07:38 | 123
又是一個(gè)自造輪子引發(fā)的血案……  回復(fù)  更多評(píng)論
  
# re: 跨模塊傳參數(shù)的教訓(xùn)
2012-07-16 09:28 | zuhd
我覺得還是傳char *比較保險(xiǎn),不要傳類  回復(fù)  更多評(píng)論
  
# re: 跨模塊傳參數(shù)的教訓(xùn)
2012-07-16 10:04 | Richard Wei
@zuhd
恩,跨模塊返回一個(gè)未初始化的CString會(huì)有同樣的問題,
所以跨模塊還是用C語言的字符串方式比較保險(xiǎn)。  回復(fù)  更多評(píng)論
  
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            亚洲欧美一区二区精品久久久| 国产午夜久久| 亚洲欧美精品一区| 亚洲女爱视频在线| 在线综合亚洲| 午夜亚洲视频| 久久婷婷色综合| 免费视频久久| 欧美精品亚洲二区| 国产精品免费区二区三区观看| 国产精品色午夜在线观看| 国产精品女人网站| 激情自拍一区| 亚洲精品一区二区三区99| 99国产精品视频免费观看一公开| 国产精品99久久久久久白浆小说| 亚洲在线中文字幕| 久久久久www| 亚洲成人中文| 亚洲最黄网站| 久久精品夜色噜噜亚洲a∨ | 亚洲电影免费观看高清完整版| 亚洲人成网站影音先锋播放| 中文成人激情娱乐网| 久久激情久久| 亚洲高清不卡在线| 亚洲私人影院在线观看| 久久九九精品99国产精品| 欧美精品免费在线观看| 国产伦精品一区二区三区四区免费 | 日韩一级大片在线| 欧美一区91| 亚洲福利在线看| 亚洲伊人网站| 欧美另类综合| **欧美日韩vr在线| 小黄鸭视频精品导航| 亚洲福利久久| 久久国产99| 国产精品美女午夜av| 亚洲黄网站黄| 久久精品一二三区| 日韩一级片网址| 久久久五月婷婷| 国产精品视频导航| 夜久久久久久| 欧美国产精品| 久久久91精品国产一区二区三区 | 午夜精品久久久久久| 欧美日韩精品二区第二页| 亚洲国产成人精品女人久久久 | 亚洲伊人色欲综合网| 欧美日本亚洲| 亚洲毛片在线观看.| 欧美1级日本1级| 久久精品亚洲精品国产欧美kt∨| 国产精品久久久久久av福利软件| 一区二区日韩伦理片| 亚洲欧洲日产国产综合网| 麻豆av一区二区三区久久| 亚洲第一网站免费视频| 玖玖视频精品| 老司机精品福利视频| 亚洲国内自拍| 亚洲激情图片小说视频| 欧美久久久久| 亚洲网址在线| 亚洲一二三区精品| 国产欧美日韩精品专区| 久久久青草婷婷精品综合日韩| 欧美专区在线播放| 亚洲电影在线观看| 欧美激情中文不卡| 欧美日韩国产页| 亚洲无亚洲人成网站77777 | 久久视频在线看| 亚洲第一精品久久忘忧草社区| 欧美大片va欧美在线播放| 免费中文日韩| 在线天堂一区av电影| 在线性视频日韩欧美| 国产午夜精品久久久久久免费视| 久久久久免费观看| 欧美激情1区| 亚洲自拍偷拍色片视频| 欧美一区二区三区在线观看视频| 在线精品在线| 亚洲精品久久在线| 国产精品色在线| 欧美va亚洲va日韩∨a综合色| 免费看成人av| 欧美一区成人| 欧美激情精品久久久六区热门 | 免费成人av| 亚洲欧美日韩国产综合| 欧美aa国产视频| 欧美日韩精品一区二区| 亚洲欧美日韩一区二区三区在线| 午夜日韩电影| 亚洲国产精品电影| 在线亚洲免费| 1024精品一区二区三区| 99综合在线| 在线观看三级视频欧美| 中文精品一区二区三区| 亚洲黄色天堂| 羞羞色国产精品| 亚洲伦伦在线| 久久久综合网站| 欧美一级午夜免费电影| 欧美激情综合| 农村妇女精品| 国产一级一区二区| 亚洲视频第一页| 亚洲卡通欧美制服中文| 欧美一区二视频| 亚洲一区综合| 欧美精品国产精品| 欧美大片在线看| 国内精品久久久久影院优| 亚洲婷婷在线| 亚洲欧美第一页| 欧美日韩中文字幕在线视频| 欧美激情成人在线| 亚洲电影激情视频网站| 久久精品电影| 久久久久在线观看| 国产日韩欧美在线播放| 亚洲砖区区免费| 亚洲欧美日韩一区在线| 欧美日韩免费观看一区| 亚洲激情影视| 日韩视频中文| 欧美伦理91| 亚洲欧洲精品一区| 亚洲老司机av| 欧美另类videos死尸| 亚洲国产精品久久久久秋霞影院 | 午夜国产一区| 欧美电影打屁股sp| 亚洲国产经典视频| 1024亚洲| 欧美激情aⅴ一区二区三区| 男男成人高潮片免费网站| 尤物yw午夜国产精品视频| 久久精品二区三区| 蜜桃精品久久久久久久免费影院| 一区二区三区在线免费视频| 香蕉久久夜色精品国产使用方法| 国产精品高潮视频| 亚洲性视频h| 久久久久成人精品免费播放动漫| 国产一区欧美| 久久野战av| 亚洲黄色免费| 亚洲一级在线观看| 国产热re99久久6国产精品| 久久疯狂做爰流白浆xx| 亚洲免费不卡| 亚洲深夜福利| 久久国产精品亚洲va麻豆| 国产专区综合网| 久久亚洲不卡| 亚洲影院一区| 国产日韩欧美精品| 久久综合久久综合这里只有精品| 欧美激情久久久久久| 中文亚洲免费| 中文一区二区| 久久综合久久综合九色| 91久久精品日日躁夜夜躁国产| 欧美日韩免费区域视频在线观看| 亚洲一区激情| 亚洲国产一区视频| 欧美在线三区| 亚洲精品欧美日韩| 国产欧美日韩另类视频免费观看| 久久久久一区二区三区| 亚洲美女视频网| 美国成人毛片| 亚洲一区久久| 亚洲国产成人在线视频| 国产精品成人一区| 麻豆免费精品视频| 亚洲综合三区| 日韩图片一区| 欧美高清在线精品一区| 亚洲欧美日韩中文播放| 91久久极品少妇xxxxⅹ软件| 国产欧美日韩一区二区三区| 欧美激情中文字幕乱码免费| 欧美自拍丝袜亚洲| 亚洲精品综合精品自拍| 欧美成人一区二免费视频软件| 欧美一区免费| 午夜精品久久久久久| 宅男噜噜噜66一区二区66| 在线观看日韩国产| 国产亚洲在线| 国产日韩久久|