BSTR Usage myths and hidden memory corruption and memory leaks

Source: Internet
Author: User

BSTR Usage myths and hidden memory corruption and memory leaks

Magictong

Brief introduction

The data structure of a BSTR is not the problem discussed in this article, but it is the foundation of this article. In solving the problem of cross-platform programming of COM, it is necessary to define a common type of string, it is invented, and its structure is easily matched to different programming environments, for C + + programmers, the most basic thing to remember is that when assigning a BSTR structure, it is not simple to call new, malloc can be done, and most of the string-related APIs and C library functions can not be used to handle a BSTR, in fact, this is one of the pitfalls of using a BSTR, in C + +, the BSTR is simple define for wchar_t*, which is easy to cause misunderstanding one of the reasons.

Today, take a look at the different role problems that a BSTR plays when it acts as a parameter to a function, when it returns a value, and when the caller and callee manipulate a BSTR. The first thing to note when you must use a BSTR when using a BSTR wrapper class CComBSTR, it will give you some additional resources to manage the work, make you a lot easier, the likelihood of error is greatly reduced.

Like a very simple natural usage: BSTR bstrinfo = L "", in fact, is wrong (of course if you say I later put Bstrinfo completely as a wchar_t* to use, then I have no words). For a BSTR variable, it is only possible to be null or a properly allocated BSTR pointer.

A BSTR is used as a basic convention for parameters and returns

1, [in\out] Parameters

For example, the function: void Getchangbstr (bstr* pbstrtitle), inside the GETCHANGBSTR function, you need to read the value of Pbstrtitle first, and then change the value of Pbstrtitle.

In this case, the callee (that is, GETCHANGBSTR) needs to release the original value in Pbstrtitle before assigning a new value to the Pbstrtitle, and then assigns the new value to the Pbstrtitle.

The caller (that is, the function that calls GETCHANGBSTR) needs to assign the correct value to the Pbstrtitle before the call is completed, and then the value of the Pbstrtitle is freed.

2, [in] parameter

For example, the function: void Puttext (BSTR bstrtext), only the value of Bstrtext must be read inside the Puttext.

In this case, the callee is free to read the value of the Bstrtext, and no other action is required.

The caller is required to assign the correct value to the Bstrtext before the argument is passed, and the value of Bstrtext needs to be freed after the call ends.

3, [out] Parameters

For example, the function: void GetText (bstr* pbstrtext), which assigns a value directly to Pbstrtext inside the GetText.

In this case, the callee assigns a value directly to the Pbstrtext, and no other action is required.

The caller cannot assign a value to Pbstrtext before the argument is passed, and the value of Pbstrtext needs to be freed after the call ends.

4. Return parameters

For example, the function: BSTR GetText (), inside the GetText will return a BSTR out. The caller returns a valid BSTR directly, and the caller needs to release the returned BSTR.

A BSTR as a parameter and a mistake to return to use

1, [in\out] Parameters

In this case, if the callee does not assign a value to the parameter, do not release the original value, because the caller is also freed according to the contract, which can cause multiple releases, which can lead to memory corruption.

void Getchangbstr (/*[in\out] */bstr* pbstrtitle)

{

Using the BS here

DoSomething (*pbstrtitle);

if (...)

{

:: SysReAllocString (*pbstrtitle, _t ("tecnet"));

}

Else

{

:: SysFreeString (*pbstrtitle); The practice here is wrong.

}

Return

}

2, [in] parameter

The callee does not release the parameters for the same reason as above, and the caller is also repeatedly freed, which can cause memory corruption.

void Puttext (/*[in] */bstr bstrtext)

{

Using the BS here

DoSomething (Bstrtext);

:: SysFreeString (Bstrtext); The practice here is wrong.

Return

}

3, [out] Parameters

If the caller assigns a value to the parameter before the argument is passed to the callee, the action is not released until the value is changed, which means there is a memory leak.

void GetText (/*[out] */bstr* pbstrtext)

{

:: SysAllocString (*pbstrtext, _t ("tecnet"));

Return

}

Use GetText

BSTR Bstrtext;

:: SysAllocString (Bstrtext, _t ("QQ"));

GetText (&bstrtext);

:: SysFreeString (Bstrtext); Unfortunately, this is actually only released once.

4. Return parameters

The callee does not release (either directly or indirectly) a BSTR returned to the caller because the caller is freed.

BSTR GetText ()

{

BSTR Bstrtext =:: SysAllocString (Bstrtext, _t ("tecnet"));

:: SysFreeString (Bstrtext); This is a tragic release.

return bstrtext;

}

Use GetText

BSTR Bstrtext = GetText (&bstrtext);

Use Bstrtext

Dosome (Bstrtext); Bstrtext has been released, the use is problematic

:: SysFreeString (Bstrtext); It's not just a matter of repeating the release.

A mistake used by a BSTR in a class

1. I want to save an [in] parameter BSTR to a class member variable

In this case, the direct assignment is not possible, because the outside caller will release the BSTR parameter, so to save, you need the class function to reapply a new BSTR.

void Csomeclass::settext (BSTR bs)

{

M_bstrtext is a member variable of Csomeclass

M_bstrtext = BS; Error procedure

M_bstrtext =:: SysReAllocString (BS); Correct practice

}

2. I want to outgoing a BSTR member variable of a class

In the same way, because the outgoing BSTR variable may be released at some time outside, it is necessary to prevent the class member variable from being released as an innocent, and to generate a valid copy.

void Csomeclass::gettext (bstr& bs)

{

M_bstrtext is a member variable of Csomeclass

BS = M_bstrtext; Error procedure

BS =:: SysAllocString (M_bstrtext); Correct practice

}

Package Class CComBSTR for BSTR

Microsoft found that we use a BSTR has the above all kinds of uncomfortable, so decided to package it, very thoughtful! Well, really intimate, one of the better package is CComBSTR (many project groups may have their own BSTR package, but in fact, it is very much the same), this package is really useful (although not provided CString so many cowhide features), use is very convenient, but, If we are wrong to use also can have nightmares, and the error is difficult to find, we have to review a few (note: The following content needs to understand the basic principles of CCOMBSTR encapsulation and provide interfaces, but these are not the content of this article to be discussed, and another package class is _bstr_t, It is managed with reference counting, which is much more complex than CComBSTR, and is not recommended for individuals _bstr_t.

1. The callee violates the use convention of the Out parameter

void GetText (/*[out]*/bstr& bstrtext)

{

CComBSTR bstrt (_t ("Qqpcmgr"));

Error: BSTRT will be automatically released, violating the use conventions of out parameters

Bstrtext = (BSTR) bstrt;

Return

//////////////////////////////////////////////////////////////////////////

The right approach, generally speaking detach, is a more efficient method.

But if BSTRT itself is a class member variable, you might want to use copy

Bstrtext = Bstrt.copy ();

Bstrtext = Bstrt.detach ();

Return

}

2. The caller violates the Out parameter use convention

void GetText (/*[out]*/bstr& bstrtext)

{

......

}

Use GetText

CComBSTR Bstrtext (L "QQ");

Memory leak, before calling GetText to empty Bstrtext

Bstrtext.empty ();

GetText (Bstrtext);

3, look at a vague point of

void GetText (/*[out]*/bstr& bstrtext)

{

......

}

Use GetText

CComBSTR Bstrtext;

BSTR bstrinfo = NULL;

GetText (Bstrinfo);

Release Bstrinfo if not shown later

There's going to be a memory leak, and this mix is dangerous.

Bstrtext = Bstrinfo;

If you want to ccombstr take over a BSTR, you can use

Bstrtext.attach (Bstrinfo);

4, repeated release, causing memory corruption

{

CComBSTR Bstrtext (L "Tencent");

Because CComBSTR overloads the operator BSTR operation, it is supported here

:: SysFreeString (Bstrtext); Error procedure, if you really want to release, you can call empty

}

Out of Bstrtext range, Bstrtext is automatically released, which can cause memory corruption

......

Reference documents

[1] BSTR Https://zh.wikipedia.org/zh-cn/BSTR

[2] Bstr_inside http://wenku.baidu.com/view/d577a1c5d5bbfd0a795673b2.html

http://blog.csdn.net/magictong/article/details/8995516

BSTR Usage myths and hidden memory corruption and memory leaks

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.