• <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>
            隨筆-380  評(píng)論-37  文章-0  trackbacks-0

            轉(zhuǎn):http://www.cnblogs.com/minggoddess/archive/2010/12/15/1907179.html

            動(dòng)態(tài)鏈接庫(kù)中分配內(nèi)存引起的

                   本文主要是探討關(guān)于在動(dòng)態(tài)鏈接庫(kù)分配的內(nèi)存在主程序中釋放所產(chǎn)生的問題,該問題是我在剛做的PJP工程中所遇到的,由于剛碰到之時(shí)感動(dòng)比較詭異(這也是學(xué)識(shí)不夠所致),所以將它寫下來,大家一起分享.

                   問題來由:

            由于該工程中要用到聲音,所以我的分工之一就是用DirectMusic和DirectSound來開發(fā)聲音播放的動(dòng)態(tài)庫(kù),以提供給該工程的兩個(gè)部分:仿真控制部分( 語(yǔ)音 )和三維部分( 場(chǎng)景聲音 )使用,兩個(gè)工程中的聲音都以單獨(dú)的線程播放,且兩個(gè)線程幾乎相同.,然而該動(dòng)態(tài)庫(kù)在以前的運(yùn)行中一直沒有出現(xiàn)過問題, 直到工程開發(fā)即將要結(jié)束階段的前一個(gè)星期,我碰才到了這個(gè)問題,首先是三維部分中聲音在第一次播放是沒有問題,在播放第二個(gè)聲音就出了問題(老是這樣),但是仿真控制部分還是沒有出現(xiàn)問題,我查不出錯(cuò)誤,就用前一天的三維的版本來運(yùn)行,重新生成后聲音播放沒有問題,初步以為是我同事當(dāng)天寫的代碼有問題,可是第二天,同樣的問題又發(fā)生了,還是那樣,三維有問題,仿真部分沒問題,怎么回事呢?我將三維的聲音線程寫成和仿真部分一樣的,還是三維出問題,仿真沒問題.我不相信是動(dòng)態(tài)庫(kù)中出問題,同一個(gè)動(dòng)態(tài)庫(kù),同樣的代碼,只是在兩個(gè)不同的程序里,為什么一個(gè)出問題,而另一個(gè)不出問題呢?

                   出錯(cuò)信息如下:

                              windows已在PowipD.exe中觸發(fā)一個(gè)斷點(diǎn).
                              其原因可能是堆被損壞,這也說明PowipD.exe中或它所加載的任何DLL中有bug.
                              輸出窗口可能提供了更多診斷信息

                   按下中斷后輸入窗口出現(xiàn)的信息如下:

                           HEAP[PowipD.exe]:Invalid Address specified to RtlValidateHeap( 01CC0000, 03723758 )
                           Windows已在PowipD.exe中觸發(fā)一個(gè)斷點(diǎn).
                           輸出窗口可能提供了更多診斷信息

                   由于這些原因讓我迷惑不解,到底是為什么出現(xiàn)這種奇怪的事情呢?問題出在那里?

             

            問題的解決:

            簡(jiǎn)單地說:DLL中分配的內(nèi)存DLL要負(fù)責(zé)釋放?。ㄒ粋€(gè)模塊分配的內(nèi)存要在同一個(gè)模塊中釋放?。?/p>

            找到解決方法后我查看了三個(gè)工程的設(shè)置(三個(gè)工程皆用VS2005開發(fā)):

                   三維:使用MDd(多線程調(diào)試DLL)運(yùn)行期庫(kù)

                   仿真控制:使用MTd(多線程調(diào)試)運(yùn)行期庫(kù)

                   聲音動(dòng)態(tài)庫(kù):使用MDd(多線程調(diào)試DLL)運(yùn)行期庫(kù)

            于是,我將三個(gè)工程皆改為:使用MDd(多線程調(diào)試DLL)運(yùn)行期庫(kù)時(shí),問題解決。

            但是如果三個(gè)工程中有的不是用C/C++寫的,或者其中有工程的設(shè)置已經(jīng)不便更改了,那又有什么辦法呢?

            該問題主要是關(guān)于DLL與進(jìn)程的地址空間的問題(下面是<<核心編程>>中的一段話):

            單個(gè)地址空間是由一個(gè)可執(zhí)行模塊和若干個(gè)DLL模塊組成,這些模塊中,有些可以鏈接到靜態(tài)版本的C/C++運(yùn)行期庫(kù), 有些可以鏈接到一個(gè)DLL版本的運(yùn)行期庫(kù),而有些模塊(如果不是用C/C++編寫的話)則根本不需要C/C++運(yùn)行期庫(kù),許多開發(fā)人員經(jīng)常會(huì)犯一個(gè)常見的錯(cuò)誤,因?yàn)樗麄兺浟巳舾蓚€(gè)C/C++運(yùn)行期庫(kù)可以存在于單個(gè)地址空間中.請(qǐng)看下面的代碼(下面代碼不是書上的):

            DLL中如下:

                   int *DllFunc()

            {

                   int *p = new int;

                   return p;

            }

             

            EXE中如下:

            void EXEFunc()

            {

                   int *p = DllFunc();

                   if( p!= NULL )

                          delete p;

            }

             

            如何看待這個(gè)問題呢?上面的代碼能夠正確運(yùn)行嗎?DLL函數(shù)分配的內(nèi)存是由EXE的函數(shù)釋放的嗎?答案是可能的.上面顯示的代碼并沒有提供足夠的信息.如果EXE和DLL都鏈接到DLL的C/C++運(yùn)行期庫(kù),那么上面的代碼將能夠很好地運(yùn)行.但是,如果兩個(gè)模塊中的一個(gè)或者兩個(gè)鏈接到靜態(tài)C/C++運(yùn)行期庫(kù),那個(gè)對(duì)delete的操作就會(huì)失敗.

            一個(gè)很方便的方法可以解決這個(gè)問題.當(dāng)一個(gè)模塊提供一個(gè)用于分配內(nèi)存塊的函數(shù)時(shí),該模塊也必須提供相應(yīng)的釋放內(nèi)存的函數(shù),將上面的代碼改成如下的樣子就不會(huì)出錯(cuò)了:

             

            DLL中如下:

                   int *DllFunc()

            {

                   int *p = new int;

                   return p;

            }

             

            void DLLDelete( int *p)

            {

                   if( p != NULL )

                          delete p;

            }

             

            EXE中如下:

            void EXEFunc()

            {

                   int *p = DllFunc();

                   DLLDelete( p );

            }

            這樣的代碼才是正確的,當(dāng)我將代碼改成如上類似后,再將三維的運(yùn)行期庫(kù)改為原來一樣(使用MDd(多線程調(diào)試DLL)運(yùn)行期庫(kù)),三維的聲音也正確無(wú)誤地播放出來了。當(dāng)你在編寫一個(gè)模塊時(shí),你時(shí)刻都得記著,別人的代碼不一定是用C/C++寫的,也有可能不能同時(shí)鏈接到DLL的C/C++運(yùn)行期庫(kù)。malloc和free函數(shù)也有類似的問題。

            當(dāng)然在你在生成你的模塊時(shí)是可以選擇運(yùn)行期庫(kù)的,VC 6.0配有6個(gè)運(yùn)行期庫(kù):其描述如下:

             

            庫(kù)名

            描述

            LibC.lib

            用于單線程應(yīng)用程序的靜態(tài)應(yīng)用程序的靜態(tài)鏈接庫(kù)      

            LibCD.lib

            用于單線程應(yīng)用程序的靜態(tài)鏈接庫(kù)的調(diào)試版

            LibCMt.lib

            用于多線程應(yīng)用程序的靜態(tài)鏈接庫(kù)的發(fā)行版

            LibCMtD.lib

            用于多線程應(yīng)用程序的靜態(tài)鏈接庫(kù)的調(diào)試版

            MSVCRt.lib

            用于動(dòng)態(tài)鏈接MSVCRt.dll庫(kù)的發(fā)行版的輸入庫(kù)

            MSVCRtD.lib

            用于動(dòng)態(tài)鏈接MSVCRtD.dll的調(diào)試版的輸入庫(kù)。該庫(kù)同時(shí)支持單線程應(yīng)用程序和多線程應(yīng)用程序

             

            而VS2005中只配了4個(gè)C/C++運(yùn)行期庫(kù),就是上表中的后面4個(gè)。

            建議各位在軟件開發(fā)時(shí)同一軟件的不同模塊最好使用一致的運(yùn)行庫(kù),否則還可能出現(xiàn)鏈接問題。

            posted on 2012-06-02 17:52 小王 閱讀(1795) 評(píng)論(1)  編輯 收藏 引用 所屬分類: VC

            評(píng)論:
            # re: 動(dòng)態(tài)鏈接庫(kù)分配的內(nèi)存在主程序中釋放所產(chǎn)生的問題 2012-06-03 02:03 | egmkang
            程序的接口有問題.
            誰(shuí)申請(qǐng)的,誰(shuí)釋放;誰(shuí)提供申請(qǐng)的接口,誰(shuí)也提供釋放的接口  回復(fù)  更多評(píng)論
              
            国产精品久久成人影院| 亚洲AV日韩AV天堂久久| 久久中文娱乐网| 91精品国产91热久久久久福利 | 久久国产精品免费一区| 蜜臀久久99精品久久久久久| 久久久久久久91精品免费观看| 99久久99这里只有免费费精品| 色综合久久88色综合天天| 波多野结衣久久精品| 996久久国产精品线观看| 久久天天婷婷五月俺也去| a级成人毛片久久| 久久精品国产亚洲AV香蕉| 精品久久久久久无码中文野结衣 | 人妻无码久久精品| 精品久久香蕉国产线看观看亚洲 | 日本欧美国产精品第一页久久| 亚洲国产美女精品久久久久∴| 久久精品国产精品亚洲下载| 欧美午夜精品久久久久免费视| 四虎久久影院| 精品久久久久久久久久久久久久久| 人人狠狠综合久久88成人| 久久亚洲精品无码VA大香大香| 久久国产免费| 久久国产精品波多野结衣AV| 久久综合综合久久狠狠狠97色88| 久久棈精品久久久久久噜噜| 日本五月天婷久久网站| 久久国产AVJUST麻豆| 热RE99久久精品国产66热| 久久久久亚洲AV综合波多野结衣 | 欧美激情精品久久久久| 久久国产热精品波多野结衣AV| 亚洲精品乱码久久久久久 | 青青青国产精品国产精品久久久久| 无码国内精品久久人妻| 国产亚洲精品美女久久久| 久久成人国产精品| 88久久精品无码一区二区毛片 |