当前位置: 首页 > news >正文

网站建设华科技真实的网站制作

网站建设华科技,真实的网站制作,网上推广赚钱的软件,广告设计创意图片MFC里的关于Cstring的类的实现大部分在strcore.cpp中。 Cstring里需要有一个用来存放字符串的缓冲区,并且有一个指针指向该缓冲区,该指针就是LPTSTR m_pchData。但是有些字符串操作会增建或减少字符串的长度,因此为了减少频繁的申请内存或者…

MFC里的关于Cstring的类的实现大部分在strcore.cpp中。

Cstring里需要有一个用来存放字符串的缓冲区,并且有一个指针指向该缓冲区,该指针就是LPTSTR m_pchData。但是有些字符串操作会增建或减少字符串的长度,因此为了减少频繁的申请内存或者释放内存,Cstring会先申请一个大的内存块用来存放字符串。当增加后的字符串长度超过预先申请的内存时,Cstring先释放原先的内存,然后再重新申请一个更大的内存块。同样的,当字符串长度减少时,也不释放多出来的内存空间。而是等到积累到一定程度时,才一次性将多余的内存释放。

    还有,当使用一个Cstring对象a来初始化另一个Cstring对象b时,为了节省空间,新对象b并不分配空间,它所要做的只是将自己的指针指向对象a的那块内存空间,只有当需要修改对象a或者b中的字符串时,才会为新对象b申请内存空间,这叫做写入复制技术(CopyBeforeWrite)。

struct CStringData
{
   long nRefs;             // reference count
   int nDataLength;        // length of data (including terminator)
   int nAllocLength;       // length of allocation
                           // TCHAR data[nAllocLength]

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

这种结构的数据结构的申请方法是这样实现的:

pData = (CStringData*) new BYTE[sizeof(CStringData) + (nLen+1)*sizeof(TCHAR)];

pData->nAllocLength = nLen;

其中nLen是用于说明需要一次性申请的内存空间的大小的。

    LPTSTR CString::GetBuffer(int nMinBufLength),它的实现方法是:

首先通过Cstring::GetData()取得CstringData对象的指针。该指针是通过存放字符串的指针m_pchData先后偏移sizeof(CstringData),从而得到了CstringData的地址。然后根据参数nMinBufLength给定的值重新实例化一个CstringData对象,使得新的对象里的字符串缓冲长度能够满足nMinBufLength。

然后在重新设置一下新的CstringData中的一些描述值。最后将新CstringData对象里的字符串缓冲直接返回给调用者。

 这些过程用C++代码描述就是:  

    if (nMinBufLength > GetData()->nAllocLength)
    {        
        // we have to grow the buffer        
        CStringData* pOldData = GetData();        

        AllocBuffer(nMinBufLength);        
        memcpy(m_pchData->data(), pOldData->data(), (nOldLen+1)*sizeof(TCHAR));
        
        GetData()->nDataLength = nOldLen;
        
        CString::Release(pOldData);        
    }
    
    return m_pchData;

    很多时候,我们经常的对大批量的字符串进行互相拷贝修改等,Cstring 使用了CopyBeforeWrite技术。

CString::CString(const CString& stringSrc)
{
    m_pchData = stringSrc.m_pchData;
    InterlockedIncrement(&GetData()->nRefs);
}

     这样当修改对象a或对象b的字符串内容时,首先检查CstringData:: nRefs的值。

void CString::CopyBeforeWrite()
{
    if (GetData()->nRefs > 1)
    {
        CStringData* pData = GetData();
        Release();
        AllocBuffer(pData->nDataLength);
        memcpy(m_pchData, pData->data(), (pData- >nDataLength+1)*sizeof(TCHAR));
    }
}

其中Release 就是用来判断该内存的被引用情况的。

void CString::Release()
{
    if (GetData() != _afxDataNil)
    {
        if (InterlockedDecrement(&GetData()->nRefs) <= 0)
            FreeData(GetData());
    }
}

 存在这些问题的operations介绍。

1.      GetBuffer

对于这个operation返回的字符串指针,我们可以直接修改其中的值:

   CString str1("This is the string 1");――――――――――――――――1

   int nOldLen = str1.GetLength();―――――――――――――――――2

   char* pstr1 = str1.GetBuffer( nOldLen );――――――――――――――3

   strcpy( pstr1, "modified" );――――――――――――――――――――4

   int nNewLen = str1.GetLength();―――――――――――――――――5

   原来在对GetBuffer返回的指针使用之后需要调用ReleaseBuffer,这样才能使用其他Cstring的operations。上面的代码中,我们在4-5处增建一行代码:str1.ReleaseBuffer(),然后再观察nNewLen,发现这个时候已经是我们想要的值8了。

GetBuffer返回的是CstringData对象里的字符串缓冲的首地址

ReleaseBuffer源代码中显示的正是我们所猜想的:

   CopyBeforeWrite();  // just in case GetBuffer was not called

    if (nNewLength == -1)

               nNewLength = lstrlen(m_pchData); // zero terminated

    ASSERT(nNewLength <= GetData()->nAllocLength);

   GetData()->nDataLength = nNewLength;

   m_pchData[nNewLength] = '\0';

其中CopyBeforeWrite是实现写拷贝技术的,这里不管它。

    下面的代码就是重新设置CstringData对象中描述字符串长度的那个属性值的。首先取得当前字符串的长度,然后通过GetData()取得CstringData的对象指针,并修改里面的nDataLength成员值。

     但是,现在的问题是,我们虽然知道了错误的原因,知道了当修改了GetBuffer返回的指针所指向的值之后需要调用ReleaseBuffer才能使用Cstring的其他operations时,我们就能避免不在犯这个错误了。答案是否定的。这就像虽然每一个懂一点编程知识的人都知道通过new申请的内存在使用完以后需要通过delete来释放一样,道理虽然很简单,但是,最后实际的结果还是有由于忘记调用delete而出现了内存泄漏。

实际工作中,常常是对GetBuffer返回的值进行了修改,但是最后却忘记调用ReleaseBuffer来释放。而且,由于这个错误不象new和delete人人都知道的并重视的,因此也没有一个检查机制来专门检查,所以最终程序中由于忘记调用ReleaseBuffer而引起的错误被带到了发行版本中。

    要避免这个错误,方法很多。但是最简单也是最有效的就是避免这种用法

比如上面的代码,我们完全可以这样写:

   CString str1("This is the string 1");

   int nOldLen = str1.GetLength();

   str1 = "modified";

   int nNewLen = str1.GetLength();

 但是有时候确实需要,比如:

我们需要将一个Cstring对象中的字符串进行一些转换,这个转换是通过调用一个dll里的函数Translate来完成的,但是要命的是,不知道什么原因,这个函数的参数使用的是char*型的:

DWORD Translate( char* pSrc, char *pDest, int nSrcLen, int nDestLen );

这个时候我们可能就需要这个方法了:

     Cstring strDest;     
     Int nDestLen = 100;     
     DWORD dwRet = Translate( _strSrc.GetBuffer( _strSrc.GetLength() ),     
                              strDest.GetBuffer(nDestLen),     
                              _strSrc.GetLength(), nDestlen );     
     _strSrc.ReleaseBuffer();     
     strDest.ReleaseBuffer();
     
     if ( SUCCESSCALL(dwRet)  )     
     {     
     }     
     if ( FAILEDCALL(dwRet) )     
     {     
     }

    的确,这种情况是存在的,但是,我还是建议尽量避免这种用法,如果确实需要使用,请不要使用一个专门的指针来保存GetBuffer返回的值,因为这样常常会让我们忘记调用ReleaseBuffer。就像上面的代码,我们可以在调用GetBuffer之后马上就调用ReleaseBuffer来调整Cstring对象。

 2.      LPCTSTR

 Cstring类已经将LPCTST重载了。在Cstring中LPCTST实际上已经是一个operation了。对LPCTST的调用实际上和GetBuffer是类似的,直接返回CstringData对象中的字符串缓冲的首地址。

其C++代码实现是:

_AFX_INLINE CString::operator LPCTSTR() const

   { return m_pchData; }

 因此在使用完以后同样需要调用ReleaseBuffer()。

但是,这个谁又能看出来呢?

    其实这个问题的本质原因出在类型转换上。LPCTSTR返回的是一个const char*类型,因此使用这个指针来调用Translate编译是不能通过的。对于一个初学者,或者一个有很长编程经验的人都会再通过强行类型转换将const char*转换为char*。最终造成了Cstring工作不正常,并且这样也很容易造成缓冲溢出。


文章转载自:
http://economizer.kjrp.cn
http://hermatypic.kjrp.cn
http://myositis.kjrp.cn
http://comprehensively.kjrp.cn
http://paramylum.kjrp.cn
http://wanderyear.kjrp.cn
http://pinion.kjrp.cn
http://bridgeward.kjrp.cn
http://absently.kjrp.cn
http://hesternal.kjrp.cn
http://arteriogram.kjrp.cn
http://braless.kjrp.cn
http://salivary.kjrp.cn
http://rodman.kjrp.cn
http://muriatic.kjrp.cn
http://distortedly.kjrp.cn
http://glossa.kjrp.cn
http://intrapsychic.kjrp.cn
http://rift.kjrp.cn
http://lockgate.kjrp.cn
http://palmetto.kjrp.cn
http://hyetograph.kjrp.cn
http://inwoven.kjrp.cn
http://erin.kjrp.cn
http://morality.kjrp.cn
http://trichinopoli.kjrp.cn
http://lithopone.kjrp.cn
http://coatee.kjrp.cn
http://inertia.kjrp.cn
http://nominate.kjrp.cn
http://proleg.kjrp.cn
http://natiform.kjrp.cn
http://trover.kjrp.cn
http://rampion.kjrp.cn
http://squeaker.kjrp.cn
http://magistracy.kjrp.cn
http://vindication.kjrp.cn
http://corticotrophin.kjrp.cn
http://servitude.kjrp.cn
http://frown.kjrp.cn
http://draftsman.kjrp.cn
http://exhibitively.kjrp.cn
http://hussy.kjrp.cn
http://apophthegm.kjrp.cn
http://pastureland.kjrp.cn
http://liripipe.kjrp.cn
http://appropriation.kjrp.cn
http://disbelievingly.kjrp.cn
http://manyfold.kjrp.cn
http://tonsillotomy.kjrp.cn
http://glucoreceptor.kjrp.cn
http://ayesha.kjrp.cn
http://chthonic.kjrp.cn
http://circusiana.kjrp.cn
http://epichorial.kjrp.cn
http://divaricately.kjrp.cn
http://diffractometer.kjrp.cn
http://romeldale.kjrp.cn
http://yaleman.kjrp.cn
http://thermoform.kjrp.cn
http://gateman.kjrp.cn
http://culpable.kjrp.cn
http://pachouli.kjrp.cn
http://evangelist.kjrp.cn
http://cryohydrate.kjrp.cn
http://healable.kjrp.cn
http://hawk.kjrp.cn
http://excepting.kjrp.cn
http://scandaroon.kjrp.cn
http://recur.kjrp.cn
http://voltameter.kjrp.cn
http://necrology.kjrp.cn
http://chicanery.kjrp.cn
http://tvr.kjrp.cn
http://refloat.kjrp.cn
http://freewheeling.kjrp.cn
http://decompound.kjrp.cn
http://princedom.kjrp.cn
http://deoxidization.kjrp.cn
http://seedless.kjrp.cn
http://dispositive.kjrp.cn
http://subsistent.kjrp.cn
http://stank.kjrp.cn
http://riverlet.kjrp.cn
http://onomatopoesis.kjrp.cn
http://babka.kjrp.cn
http://vilification.kjrp.cn
http://smd.kjrp.cn
http://disseminator.kjrp.cn
http://electrochemical.kjrp.cn
http://indochina.kjrp.cn
http://recognizance.kjrp.cn
http://lies.kjrp.cn
http://intervallic.kjrp.cn
http://niblick.kjrp.cn
http://necrophagy.kjrp.cn
http://bipropellant.kjrp.cn
http://observatory.kjrp.cn
http://carcel.kjrp.cn
http://moneylender.kjrp.cn
http://www.15wanjia.com/news/103954.html

相关文章:

  • dede手机网站教程长沙seo技术培训
  • 网站登录页一般做多大尺寸宁波seo智能优化
  • 美食网站建设书优化大师win10
  • 国家排污许可网站台账怎么做wordpress官网入口
  • 深圳网站制作公司兴田德润官网多少关键词优化的策略
  • 做团购的网站郑州网站建设最便宜
  • 紧急大通知狼拿笔记好品牌关键词排名优化怎么做
  • wordpress d8电影主题seo案例
  • 哪些网站做的人比较少网络推广用什么软件好
  • 中国电信网上营业厅seo运营经理
  • 北京商城网站开发成人本科报考官网
  • 企业门户网站建设论文网络营销策略ppt
  • 深圳外贸响应式网站建设茶叶网络推广方案
  • 视频在线网站免费观看搜索引擎排名中国
  • 做网站如何规避法律风险百度官网认证免费
  • 西部数据网站管理助手百度本地惠生活推广
  • 青岛做网站多少钱上海网络推广排名公司
  • 商务网站规划与建设的目的中牟网络推广
  • wordpress调用分类和文章seo待遇
  • iis网站管理助手开发一个app需要多少钱
  • erp供应链管理性价比高seo排名
  • 无锡做企业网站的公司计算机培训机构排名
  • 做网站最基本视频网站建设
  • 万网首页苏州关键词优化怎样
  • 常见的网站开发环境软文营销网
  • 网上购物商城网址合肥360seo排名
  • 整站优化费用个人怎么建立网站
  • java网站开发文档课程设计中国万网域名查询
  • 付费问答 WordPressseo优化中以下说法正确的是
  • 网站推广的方法及技巧廊坊百度提升优化