• <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)鏈接庫中分配內(nèi)存引起的

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

                   問題來由:

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

             

            問題的解決:

            簡單地說:DLL中分配的內(nèi)存DLL要負(fù)責(zé)釋放!(一個(gè)模塊分配的內(nèi)存要在同一個(gè)模塊中釋放!)

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

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

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

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

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

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

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

            單個(gè)地址空間是由一個(gè)可執(zhí)行模塊和若干個(gè)DLL模塊組成,這些模塊中,有些可以鏈接到靜態(tài)版本的C/C++運(yùn)行期庫, 有些可以鏈接到一個(gè)DLL版本的運(yùn)行期庫,而有些模塊(如果不是用C/C++編寫的話)則根本不需要C/C++運(yùn)行期庫,許多開發(fā)人員經(jīng)常會(huì)犯一個(gè)常見的錯(cuò)誤,因?yàn)樗麄兺浟巳舾蓚€(gè)C/C++運(yùn)行期庫可以存在于單個(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)行期庫,那么上面的代碼將能夠很好地運(yùn)行.但是,如果兩個(gè)模塊中的一個(gè)或者兩個(gè)鏈接到靜態(tài)C/C++運(yùn)行期庫,那個(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)行期庫改為原來一樣(使用MDd(多線程調(diào)試DLL)運(yùn)行期庫),三維的聲音也正確無誤地播放出來了。當(dāng)你在編寫一個(gè)模塊時(shí),你時(shí)刻都得記著,別人的代碼不一定是用C/C++寫的,也有可能不能同時(shí)鏈接到DLL的C/C++運(yùn)行期庫。malloc和free函數(shù)也有類似的問題。

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

             

            庫名

            描述

            LibC.lib

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

            LibCD.lib

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

            LibCMt.lib

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

            LibCMtD.lib

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

            MSVCRt.lib

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

            MSVCRtD.lib

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

             

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

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

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

            評(píng)論:
            # re: 動(dòng)態(tài)鏈接庫分配的內(nèi)存在主程序中釋放所產(chǎn)生的問題 2012-06-03 02:03 | egmkang
            程序的接口有問題.
            誰申請(qǐng)的,誰釋放;誰提供申請(qǐng)的接口,誰也提供釋放的接口  回復(fù)  更多評(píng)論
              
            久久这里只精品国产99热| 性高湖久久久久久久久| 国产一区二区精品久久| 色综合久久最新中文字幕| 国产日韩欧美久久| 中文字幕久久亚洲一区| 精品综合久久久久久97超人| 亚洲一区二区三区日本久久九| 久久精品国产精品亚洲下载| 伊人久久大香线蕉综合网站| 久久综合久久自在自线精品自| 狠狠色丁香久久综合婷婷| A级毛片无码久久精品免费| 久久精品国内一区二区三区| 国产成人精品综合久久久久 | 国产精品亚洲美女久久久| 亚洲国产一成久久精品国产成人综合 | 99久久www免费人成精品| 思思久久99热只有频精品66| 99久久国产热无码精品免费| 亚洲AV无码1区2区久久| 亚洲va中文字幕无码久久| 国产一区二区久久久| 久久久精品波多野结衣| 久久天天日天天操综合伊人av| 久久精品国产99久久无毒不卡| 久久亚洲精品国产精品| 亚洲精品国精品久久99热一| 精品国产日韩久久亚洲| 日本人妻丰满熟妇久久久久久| 亚洲午夜久久久影院伊人| 韩国免费A级毛片久久| 国产精品久久99| 狠狠色丁香久久婷婷综合_中| 亚洲国产精品无码久久| 国产激情久久久久影院| 久久亚洲中文字幕精品一区| 久久精品亚洲日本波多野结衣| 久久久久综合国产欧美一区二区| 人妻中文久久久久| 国产精品成人久久久久久久|