码迷,mamicode.com
首页 > 其他好文 > 详细

CComBSTR的生命期

时间:2014-08-01 19:18:02      阅读:302      评论:0      收藏:0      [点我收藏+]

标签:style   blog   color   使用   代码   div   管理   c++   

CComBSTR会自动管理字符串的内存空间,在析构时释放空间。由于C++对象在出其作用域时会进行析构。所以有一些情形下,使用CComBSTR容易犯下错误。
来看以下代码:

    BSTR bstr1 = CComBSTR(L"hello");
    BSTR bstr2 = CComBSTR(L"world");

    TRACE(L"%s, %s\n", bstr1, bstr2);

本来可能预期输出的hello, world
而实际输出是world, world

 

这是因为在赋值语句完成之后,CComBSTR(L”hello”)就析构了释放了空间,bstr1指向了这块被释放的内存。在随后的赋值语句中,CComBSTR(L”world”)又利用了这块内存。然后bstr1和bstr2就指向了同一块内存。

修改代码如下:

    BSTR bstr1 = CComBSTR(L"hello");
    BSTR bstr2 = CComBSTR(L"world");

    TRACE(L"%s, %s\n", bstr1, bstr2);
    TRACE(L"bstr1[%x] %s\n", bstr1, bstr1);
    TRACE(L"bstr2[%x] %s\n", bstr2, bstr2);

输出结果为:
world, world
bstr1[6f8b94] world
bstr2[6f8b94] world

从其汇编码也可以看出:

BSTR bstr1 = CComBSTR(L"hello");
011B76D2  mov         eax,120DDB0h 
011B76D7  test        eax,eax 
011B76D9  jne         testBSTR+44h (11B76E4h) 
011B76DB  mov         dword ptr [ebp-38h],0 
011B76E2  jmp         testBSTR+75h (11B7715h) 
011B76E4  mov         esi,esp 
011B76E6  push        120DDB0h 
011B76EB  call        dword ptr [__imp__SysAllocString@4 (16EF3DCh)] 
011B76F1  cmp         esi,esp 
011B76F3  call        _RTC_CheckEsp (11F1FF0h) 
011B76F8  mov         dword ptr [ebp-38h],eax 
011B76FB  xor         ecx,ecx 
011B76FD  cmp         dword ptr [ebp-38h],0 
011B7701  sete        cl   
011B7704  movzx       edx,cl 
011B7707  test        edx,edx 
011B7709  je          testBSTR+75h (11B7715h) 
011B770B  push        8007000Eh 
011B7710  call        ATL::AtlThrowImpl (11B1109h) 
011B7715  lea         eax,[ebp-38h] 
011B7718  mov         dword ptr [ebp-88h],eax 
011B771E  mov         ecx,dword ptr [ebp-88h] 
011B7724  mov         edx,dword ptr [ecx] 
011B7726  mov         dword ptr [bstr1],edx 
011B7729  mov         esi,esp 
011B772B  mov         eax,dword ptr [ebp-38h] 
011B772E  push        eax  
011B772F  call        dword ptr [__imp__SysFreeString@4 (16EF3D8h)] 
011B7735  cmp         esi,esp 
011B7737  call        _RTC_CheckEsp (11F1FF0h) 
    BSTR bstr2 = CComBSTR(L"world");

在bstr2赋值语句之前就已经调用__imp_SysFreeString释放空间了。

 

解决办法是将CComBSTR作用域加大,比如构造作用域在函数范围内的两个变量str1和str2。

代码如下:

    CComBSTR str1(L"hello");
    CComBSTR str2(L"world");

    TRACE(L"%s, %s\n", str1, str2);
    TRACE(L"str1[%x] %s\n", str1, str1);
    TRACE(L"str2[%x] %s\n", str2, str2);

输出结果如下:
hello, world
str1[107bd5c] hello
str2[107bd34] world

从反汇编可以看出__imp__SysFreeString是在函数退出后调用。

 

结论:

在使用CComBSTR时,尽量不要做复杂操作,而且不要让其出现在等号右边。CA2T之类的也是。MSDN上说的比较详细,还有关于CComBSTR导致内存泄露的,具体参见MSDN。

 

CComBSTR的生命期,布布扣,bubuko.com

CComBSTR的生命期

标签:style   blog   color   使用   代码   div   管理   c++   

原文地址:http://www.cnblogs.com/shokey520/p/3885421.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!