• <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>

            elva

            CString的線程安全問題

            在多線程中使用一個局部CString變量相加時發現相加的結果是后一個字符串值,沒有時間過多研究,只好改成了char*,不過如下方法也可以避免:
            CWin32Heap stringHeap( HEAP_NO_SERIALIZE, 00 );
            CAtlStringMgr stringMgr( 
            &stringHeap );
            CString strstate(
            &stringMgr );

            找了一些資料貼上來希望對過客有用:
            http://www.shnenglu.com/alantop/archive/2008/07/10/55786.html

            討論CString線程安全性問題(內存泄漏)

            CString在線程處理中,稍有處理不當,極易引起內存泄漏。
            讓我們來看一個例子:
            在線程函數中使用如下代碼

            CString strstate;    
            strstate.Format(
            "正在解密,請稍后... (共 %d 張地圖)",p->m_countmap);

            可以看到非常簡單,在debug下,很容易看到如下的內存泄漏。



            怎么回事?
            先把修改好的代碼放上來
            CWin32Heap stringHeap( HEAP_NO_SERIALIZE, 00 );
            CAtlStringMgr stringMgr( 
            &stringHeap );
            CString strstate(
            &stringMgr );
            strstate.Format(
            "正在解密,請稍后... (共 %d 張地圖)",p->m_countmap);
            如上代碼才具有線程安全性。

            http://msdn.microsoft.com/zh-cn/library/cc485480(VS.71).aspx

            Visual C++ 概念:添加功能
            自定義字符串管理器的實現(基本方法)

            為字符串數據自定義內存分配方案的最簡單的方式是使用 ATL 提供的 CAtlStringMgr 類,但您需要自己提供內存分配例程。CAtlStringMgr 的構造函數采用單一參數:即指向 IAtlMemMgr 對象的指針。IAtlMemMgr 是提供到堆的一般接口的抽象基類。通過 IAtlMemMgr 接口,CAtlStringMgr 分配、重新分配和釋放用于存儲字符串數據的內存。您既可以自已實現 IAtlMemMgr 接口,也可以使用由 ATL 提供的五個內存管理器類之一。ATL 提供的內存管理器只包裝現有的內存分配功能:

            要進行字符串內存管理,最有用的類是 CWin32Heap,因為它使您能夠創建多個獨立的堆。例如,如果使用僅用于字符串的獨立堆,可進行以下操作:

            //Declare a thread-safe, growable, private heap with initial size 0
            CWin32Heap g_stringHeap( 0, 0, 0 );
            // Declare a string manager that uses the private heap
            CAtlStringMgr g_stringMgr( &g_stringHeap ); 

            要使用此專用的字符串管理器來管理 CString 變量的內存,請將一個指針傳遞給管理器作為 CString 變量的構造函數的一個參數:

            void PrintPowers( int nBase )
            {
            int n = 1;
            for( int nPower = 0; nPower < 10; nPower++ )
            {
            // Use the private string manager, instead of the default
            CString strPower( &g_stringMgr );
            strPower.Format( "%d", n );
            printf( "%s\n", LPCSTR( strPower ) );
            n *= nBase;
            }
            }

            http://blog.csdn.net/zero_dian/archive/2006/01/08/573352.aspx  談新手對CString的使用
            CString類功能強大,比STL的string類有過之無不及.新手使用CString時,都會被它強大的功能所吸引.然而由于對它內部機制的不了解,新手在將CString向C的字符數組轉換時容易出現很多問題.因為CString已經重載了LPCTSTR運算符,所以CString類向const char *轉換時沒有什么麻煩,如下所示:
              char a[100];
              CString str("aaaaaa");
              strncpy(a,(LPCTSTR)str,sizeof(a));
              或者如下:

              strncpy(a,str,sizeof(a));

              以上兩種用法都是正確地.因為strncpy的第二個參數類型為const char *.所以編譯器會自動將CString類轉換成const char *.很多人對LPCTSTR是什么東西迷惑不解,讓我們來看看:

              1.LP表示長指針,在win16下有長指針(LP)和短指針(P)的區別,而在win32下是沒有區別的,都是32位.所以這里的LP和P是等價的.

              2.C表示const

              3.T是什么東西呢,我們知道TCHAR在采用UNICODE方式編譯時是wchar_t,在普通時編譯成char那么就可以看出LPCTSTR(PCTSTR)在UINCODE時是const wchar_t *,PCWSTR,LPCWSTR,在多字節字符模式時是const char *, PCSTR,LPCSTR.接下來我們看在非UNICODE情況下,怎樣將CString轉換成char *,很多初學者都為了方便采用如下方法:
              (char *)(LPCSTR)str

              這樣對嗎?我們首先來看一個例子:
              CString str("aa");
              strcpy((char *)(LPCTSTR)str,"aaaaaaaa");
              cout<<(LPCTSTR)str<<endl;

              在Debug下運行出現了異常,我們都知道CString類內部有自己的字符指針,指向一個已分配的字符緩沖區.如果往里面寫的字符數超出了緩沖區范圍,當然會出現異常.但這個程序在Release版本下不會出現問題.原來對CString類已經進行了優化.當需要分配的內存小于64字節時,直接分配64字節的內存,以此類推,一般CString類字符緩沖區的大小為64,128,256,512...這樣是為了減少內存分配的次數,提高速度.

              那有人就說我往里面寫的字符數不超過它原來的字符數,不就不會出錯了,比如
              CString str("aaaaaaa");
              strcpy((char *)(LPCTSTR)str,"aa");
              cout<<(LPCTSTR)str<<endl;

              這樣看起來是沒什么問題.我們再來看下面這個例子:
              CString str("aaaaaaa");
              strcpy((char *)(LPCTSTR)str,"aa");
              cout<<(LPCTSTR)str<<endl;
              cout<<str.GetLength()<<endl;

              我們看到str的長度沒有隨之改變,繼續為7而不是2.還有更嚴重的問題:
              CString str("aaaaaaa");
              CString str1 = str;
              strcpy((char *)(LPCTSTR)str,"aa");
              cout<<(LPCTSTR)str<<endl;
              cout<<(LPCTSTR)str1<<endl;

              按說我們只改變了str,str1應該沒有改變呀,可是事實時他們都變成了"aa".難道str和str1里面的字符指針指向的緩沖區是一個.我們在Effective C++里面得知,如果你的類內部有包含指針,請為你的類寫一個拷貝構造函數和賦值運算符.不要讓兩個對象內部的指針指向同一區域,而應該重新分配內存.難道是微軟犯了錯?

              原來這里還有一個"寫時復制"和"引用計數"的概念.CString類的用途很廣,這樣有可能在系統內部產生大量的CString臨時對象.這時為了優化效率,就采用在系統軟件內部廣泛使用的"寫時復制"概念.即當從一個CString產生另一個CString并不復制它的字符緩沖區內容,而只是將字符緩沖區的"引用計數"加1.當需要改寫字符緩沖區內的內容時,才分配內存,并復制內容.以后我會給出一個"寫時復制"和"引用計數"的例子我們回到主題上來,當我們需要將CString轉換成char *時,我們應該怎么做呢?其時只是麻煩一點,如下所示:
              CString str("aaaaaaa");
              strcpy(str.GetBuffer(10),"aa");
              str.ReleaseBuffer();

              當我們需要字符數組時調用GetBuffer(int n),其中n為我們需要的字符數組的長度.使用完成后一定要馬上調用ReleaseBuffer();還有很重要的一點就是,在能使用const char *的地方,就不要使用char *


            posted on 2008-12-22 17:14 葉子 閱讀(4636) 評論(0)  編輯 收藏 引用 所屬分類: C\C++

            精品水蜜桃久久久久久久| 久久er国产精品免费观看8| 国产精品伦理久久久久久| 一本久久综合亚洲鲁鲁五月天亚洲欧美一区二区 | 久久一区二区三区免费| 国产亚洲综合久久系列| 亚洲午夜久久久| 亚洲va久久久噜噜噜久久| 亚洲国产精品综合久久一线 | 色综合久久中文字幕无码| 狠狠色婷婷综合天天久久丁香 | 一本综合久久国产二区| 久久精品人人槡人妻人人玩AV| 欧美与黑人午夜性猛交久久久 | 久久久无码精品亚洲日韩按摩| 国产精品一久久香蕉国产线看| 无码国内精品久久人妻蜜桃| 91精品国产乱码久久久久久 | 亚洲伊人久久成综合人影院| 久久精品国产亚洲AV无码偷窥| 久久亚洲电影| 国产激情久久久久影院小草| 久久久久免费看成人影片| 精品久久久久久无码不卡| 综合久久给合久久狠狠狠97色| 99精品国产在热久久无毒不卡 | 无码久久精品国产亚洲Av影片 | 久久婷婷久久一区二区三区| 久久精品国产秦先生| 精产国品久久一二三产区区别 | 亚洲国产一成人久久精品| 久久男人AV资源网站| 国产精品久久久天天影视| 久久久久久精品无码人妻| 午夜视频久久久久一区| 久久久久久久综合日本| 伊人色综合久久天天网| 青青青青久久精品国产h久久精品五福影院1421 | 97精品国产91久久久久久| 久久久久免费看成人影片| 精品国产乱码久久久久久1区2区|