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