您的位置:首页 > Web前端

GetBuffer--ReleaseBuffer问题

2012-09-21 14:25 225 查看
CString CConLog::ReadConfig(CString section,CString key)

{

GetPrivateProfileString(section,key,_T(""),m_sReadPath.GetBuffer(MAX_PATH),MAX_PATH,m_sIniPath);

m_sReadPath.ReleaseBuffer();//不释放出错

return m_sReadPath;

}

对于GetBuffer() 与 ReleaseBuffer() 的一些分析 收藏

先 转载一段别人的文章
CString类的这几个函数, 一直在用, 但总感觉理解的不够透彻, 不时还有用错的现象. 今天抽时间和Nico一起分析了一下, 算是拨开了云雾:

GetBuffer和ReleaseBuffer是一套需要配合使用的函数, 与GetBufferSetLength相比, 优点是如果分配的空间大于实际保存的字符串(0结尾), ReleaseBuffer会把多余申请的空间释放, 归还给系统; 但使用时需要注意以下问题: 如果要保存的字符串为abc(0结尾), 则GetBuffer参数应至少为3; 如果要保存的内容不是以0结尾, 比如是读取文件数据, 则GetBuffer参数如果大于文件长度时, ReleaseBuffer参数一定要为文件长度(如果GetBuffer参数为文件长度的话不存在问题,
ReleaseBuffer参数可以为默认-1)!

CString csStr;
LPTSTR lpsz = csStr.GetBuffer(100);
lpsz[0] = 'a';
lpsz[1] = 'b';
lpsz[2] = '\0';
csStr.ReleaseBuffer();
int nLength = csStr.GetLength();
GetBufferSetLength相对比较容易理解, 它申请一个指定长度的空间, 即使里面最终保存的字符串长度小于申请的空间长度, 也不会将多余空间释放.

CString csStr;
LPTSTR lpsz = csStr.GetBufferSetLength(100);
lpsz[0] = 'a';
lpsz[1] = 'b';
lpsz[2] = '\0';
int nLength = csStr.GetLength();
对于红色部分,自己写代码时的确遇到过这样的问题:代码如下
CString temp;

ULONGLONG dwcount = Input_File.GetLength();

//UINT dwcount = (UINT)Input_File.GetLength();

Input_File.Read(temp.GetBuffer(dwcount),dwcount);

temp.ReleaseBuffer(dwcount);
若temp.ReleaseBuffer()不指定参数,执行这一步是会遇到错误,所以,类似的文件读取操作,releasebuffer的时候还是指定一个与getbuffer一样的参数为好
另:对于
(如果GetBuffer参数为文件长度的话不存在问题, ReleaseBuffer参数可以为默认-1)!
我设置temp.ReleaseBuffer(-1);此句执行的时候仍然出现错误,故还是指定文件长度为好

接下来看看其他的代码
CString str;

BROWSEINFO bi;

TCHAR name[MAX_PATH];

ZeroMemory(&bi,sizeof(BROWSEINFO));

bi.hwndOwner = GetSafeHwnd();

bi.pszDisplayName = name;

bi.lpszTitle = _T("选择文件夹");

bi.ulFlags = BIF_RETURNFSANCESTORS;

LPITEMIDLIST idl = SHBrowseForFolder(&bi);

if(idl == NULL)

return;

SHGetPathFromIDList(idl, str.GetBuffer(MAX_PATH));
////1

//CString aa = str.GetBuffer(MAX_PATH);

//CString bb = str; //运行此句之后,str内容变成乱码

//int a = aa.GetLength();

//int b = str.GetLength();

//LPTSTR cc = str.GetBuffer(MAX_PATH);

//LPTSTR dd = bb.GetBuffer(MAX_PATH);

//cc[1] = 'a';
//bb.ReleaseBuffer();
debug 参数如下图所示:

////2

CString aa = str.GetBuffer(MAX_PATH);

int a = aa.GetLength();

int b = str.GetLength(); //b无法获取str的长度

LPTSTR cc = str.GetBuffer(MAX_PATH);

cc[1] = 'a';

int e = str.GetLength(); //e无法正确获取str的长度,与3不同之处在于此处的str在蓝色字体getbuffer后未releasebuffer //妥善的做法是在两次str.getbuffer与str.GetLength()之间都都releasebuffer()下。

str.ReleaseBuffer();

int d = str.GetLength();
debug 参数如下所示:

////3

//CString aa = str.GetBuffer(MAX_PATH);

//str.ReleaseBuffer();

//CString bb = str; //bb的内容正确

//int a = aa.GetLength();

//int b = str.GetLength();

//LPTSTR cc = str.GetBuffer(MAX_PATH);

//LPTSTR dd = bb.GetBuffer(MAX_PATH);

//cc[1] = 'a';

//int d = str.GetLength(); //此处虽然可以正确获取str的值,但是在GetBuffer()后,最好还是在cc[1] = ‘a’ 后releasebuffer()一次。
//为何不再cc[1]
= ‘a’前releasebuffer的原因: 虽然此处str仍然会变成”Ca\…..”,但是根据MSDN:在调用ReleaseBuffer之后,由GetBuffer返回的地址也许就无效了,因为其它的CString操作可能会导致CString缓冲区被重新分配。如果你没有改变此CString的长度,则缓冲区不会被重新分配。 妥当的做法是在cc[1]后releasebuffer
debug参数值如下所示:

////4
str.ReleaseBuffer(); // 对上面的SHGetPathFromIDList(idl,
str.GetBuffer(MAX_PATH)); 进行的释放操作

CString aa = str.GetBuffer(MAX_PATH);

CString bb = str; // 执行完此句后,str的值不会变成乱码,和1类比

int f = str.GetLength(); //和1比,此处可以正确获取长度
str.ReleaseBuffer();

int a = aa.GetLength();

int b = str.GetLength();

CString ff = str.GetBuffer(MAX_PATH);

LPTSTR dd = bb.GetBuffer(MAX_PATH);

int d = str.GetLength();

对于一个CString 进行GetBuffer后,在进行该CString 的其他 CString 函数操作(尤其是 “=” “+” 等容易忽视的 CString 操作)前ReleaseBuffer(虽然从此处的几段代码执行情况来看,表面上在GetBuffer后在一次执行 CString操作不会导致错误,但是进行第二次CString 操作时就会产生错误。为了安全起见,getbuffer后需要在次执行CString的函数操作,先ReleaseBuffer()).
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: