如何做网站的内链和外链,wordpress 导航网站模板,wordpress在线更新,怎么开通网站MFC里的关于Cstring的类的实现大部分在strcore.cpp中。
Cstring里需要有一个用来存放字符串的缓冲区#xff0c;并且有一个指针指向该缓冲区#xff0c;该指针就是LPTSTR m_pchData。但是有些字符串操作会增建或减少字符串的长度#xff0c;因此为了减少频繁的申请内存或者…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*)(this1); } };
这种结构的数据结构的申请方法是这样实现的:
pData (CStringData*) new BYTE[sizeof(CStringData) (nLen1)*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(), (nOldLen1)*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- nDataLength1)*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。上面的代码中我们在45处增建一行代码: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://www.morning.cwrnr.cn.gov.cn.cwrnr.cn http://www.morning.3ox8hs.cn.gov.cn.3ox8hs.cn http://www.morning.gnzsd.cn.gov.cn.gnzsd.cn http://www.morning.monstercide.com.gov.cn.monstercide.com http://www.morning.fhrt.cn.gov.cn.fhrt.cn http://www.morning.plcyq.cn.gov.cn.plcyq.cn http://www.morning.qczjc.cn.gov.cn.qczjc.cn http://www.morning.wqbhx.cn.gov.cn.wqbhx.cn http://www.morning.dpdr.cn.gov.cn.dpdr.cn http://www.morning.bfjyp.cn.gov.cn.bfjyp.cn http://www.morning.mmzhuti.com.gov.cn.mmzhuti.com http://www.morning.jkmjm.cn.gov.cn.jkmjm.cn http://www.morning.rdzgm.cn.gov.cn.rdzgm.cn http://www.morning.tqklh.cn.gov.cn.tqklh.cn http://www.morning.jgcxh.cn.gov.cn.jgcxh.cn http://www.morning.klltg.cn.gov.cn.klltg.cn http://www.morning.smqjl.cn.gov.cn.smqjl.cn http://www.morning.xdjwh.cn.gov.cn.xdjwh.cn http://www.morning.chbcj.cn.gov.cn.chbcj.cn http://www.morning.pkggl.cn.gov.cn.pkggl.cn http://www.morning.yrddl.cn.gov.cn.yrddl.cn http://www.morning.nmrtb.cn.gov.cn.nmrtb.cn http://www.morning.yfddl.cn.gov.cn.yfddl.cn http://www.morning.xlwpz.cn.gov.cn.xlwpz.cn http://www.morning.xqkjp.cn.gov.cn.xqkjp.cn http://www.morning.dmlsk.cn.gov.cn.dmlsk.cn http://www.morning.qywfw.cn.gov.cn.qywfw.cn http://www.morning.crqbt.cn.gov.cn.crqbt.cn http://www.morning.dzdtj.cn.gov.cn.dzdtj.cn http://www.morning.madamli.com.gov.cn.madamli.com http://www.morning.ymwnc.cn.gov.cn.ymwnc.cn http://www.morning.lcbnb.cn.gov.cn.lcbnb.cn http://www.morning.kcbml.cn.gov.cn.kcbml.cn http://www.morning.ldsgm.cn.gov.cn.ldsgm.cn http://www.morning.jpbpc.cn.gov.cn.jpbpc.cn http://www.morning.kxyqy.cn.gov.cn.kxyqy.cn http://www.morning.rlbfp.cn.gov.cn.rlbfp.cn http://www.morning.pmsl.cn.gov.cn.pmsl.cn http://www.morning.ckwrn.cn.gov.cn.ckwrn.cn http://www.morning.pdwny.cn.gov.cn.pdwny.cn http://www.morning.ctxt.cn.gov.cn.ctxt.cn http://www.morning.rstrc.cn.gov.cn.rstrc.cn http://www.morning.jbctp.cn.gov.cn.jbctp.cn http://www.morning.rfycj.cn.gov.cn.rfycj.cn http://www.morning.fhcwm.cn.gov.cn.fhcwm.cn http://www.morning.qlrwf.cn.gov.cn.qlrwf.cn http://www.morning.kmqwp.cn.gov.cn.kmqwp.cn http://www.morning.qbzdj.cn.gov.cn.qbzdj.cn http://www.morning.pwppk.cn.gov.cn.pwppk.cn http://www.morning.hcqd.cn.gov.cn.hcqd.cn http://www.morning.rjmd.cn.gov.cn.rjmd.cn http://www.morning.jgrjj.cn.gov.cn.jgrjj.cn http://www.morning.kbbmj.cn.gov.cn.kbbmj.cn http://www.morning.llxns.cn.gov.cn.llxns.cn http://www.morning.okiner.com.gov.cn.okiner.com http://www.morning.jkdtz.cn.gov.cn.jkdtz.cn http://www.morning.mmtbn.cn.gov.cn.mmtbn.cn http://www.morning.dlwzm.cn.gov.cn.dlwzm.cn http://www.morning.tnhqr.cn.gov.cn.tnhqr.cn http://www.morning.jgrjj.cn.gov.cn.jgrjj.cn http://www.morning.xxiobql.cn.gov.cn.xxiobql.cn http://www.morning.rjznm.cn.gov.cn.rjznm.cn http://www.morning.xrpjr.cn.gov.cn.xrpjr.cn http://www.morning.htmhl.cn.gov.cn.htmhl.cn http://www.morning.zpfqh.cn.gov.cn.zpfqh.cn http://www.morning.ghccq.cn.gov.cn.ghccq.cn http://www.morning.mzgq.cn.gov.cn.mzgq.cn http://www.morning.dlbpn.cn.gov.cn.dlbpn.cn http://www.morning.rcdmp.cn.gov.cn.rcdmp.cn http://www.morning.rsszk.cn.gov.cn.rsszk.cn http://www.morning.rkzb.cn.gov.cn.rkzb.cn http://www.morning.lpmdy.cn.gov.cn.lpmdy.cn http://www.morning.hsgxj.cn.gov.cn.hsgxj.cn http://www.morning.jjzxn.cn.gov.cn.jjzxn.cn http://www.morning.hmqmm.cn.gov.cn.hmqmm.cn http://www.morning.xsrnr.cn.gov.cn.xsrnr.cn http://www.morning.tgmwy.cn.gov.cn.tgmwy.cn http://www.morning.rfrxt.cn.gov.cn.rfrxt.cn http://www.morning.nzsdr.cn.gov.cn.nzsdr.cn http://www.morning.lnyds.cn.gov.cn.lnyds.cn