473,385 Members | 2,162 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

BSTR, _bstr_t issues occuring on our Windows 2003 Server

We have server components which were created by a third party and
compiled in VC++5 (sp3). They run fine on NT4 and 2000, however during
testing of our migration to Server 2003, these components have been
failing when performing Data Access functions. In particular we have
been having problems with BSTR and _bstr_t.

_bstr_t(BSTR*, 1) is the original code that the problem started with.
Other findings are -

1) Converting a BSTR* to a _bstr_t when the length of the message in
BSTR* is 16,382 characters or more, gives errors.
a) Using _bstr_t(BSTR*, 1) causes the application to crash. fcopy=1
b) Using _bstr_t(BSTR*) ). In this case, fcopy=0 by default.
i) When message length is 16,382 or more characters - converts the
message but the first two characters are corrupted and unreadable
ii) When message length is much higher, ex:32,758 characters, the
application crashes.
2) The length of message content is not an issue when converting
_bstr_t to a BSTR.

_bstr_t(BSTR*, 1) worked fine even for message lengths as high as
50,292 characters, on the Windows NT 4.0 and Windows 2000 servers.

Anyone have any advice, input?

Mar 10 '06 #1
5 2641
bluter wrote:
_bstr_t(BSTR*, 1) is the original code that the problem started with.


are you sure you are using BSTR* (that is pointer to BSTR)? This is
wrong, _bstr_t is abstraction for BSTR which in itself is a pointer
(without an extra pointer). Futhermore, if you happen to mix wchar_t*
with BSTR, you may NOT pass wchar_t* where BSTR is expected, because
BSTR is expected to be prefixed with length (and wchar_t* is just a
pointer, with no magic, that is no prefix). And if you happen to pass
BSTR as a result of function, be very, very careful not to leak it or
double free; or simply replace it with _bstr_t to keep things tidy.
B.
Mar 10 '06 #2
We are using BSTR and it is being passed back as a result of a
function. This is all over the project and the way it is setup, it is
close to impossible for changing it.
We do suspect that there is a leak occurring during at the time the
result is being passed back from the lower function to the calling
function. This happens in Windows 2003 server and was not an issue in
Windows NT 4.0 or Windows 2000 servers. Are you aware of similar issues
with VC++5.0 applications running on Windows 2003 servers?
Could you suggest ways to prevent leaks/double free when BSTR is passed
back as result of a function.

Code shown below:

const string FMLMsgProxy::getMsg ()
{
BSTR bstrMsg = m_pFINMsg->getMsg();
_bstr_t bstrtMsg(bstrMsg); //Code breaks here
------------------
---------------
}

STDMETHODIMP CFINMsg::getMsg(BSTR * o_Msg)
{
--------------------------------
-----------------------------
*o_Msg = m_OGMsg.copy(); //m_OGMsg is declared as _bstr_t
return S_OK;
}

Mar 14 '06 #3
su**************@gmail.com wrote:
We do suspect that there is a leak occurring during at the time the
no, but you might have a leak somewhere else, as you apparently do not
understand some things about _bstr_t and BSTR. And you have other
problems, described below.
const string FMLMsgProxy::getMsg ()
{
BSTR bstrMsg = m_pFINMsg->getMsg();
_bstr_t bstrtMsg(bstrMsg); //Code breaks here
I assume that getMsg (as called above) is actually wrapper provided by
compiler COM support, that is #import and accompanying *.tlh and *.tli
files. The wrapper funtion returns temporary object of type _bstr_t .
Just after initialization of BSTR bstrMsg this temporary object is
destroyed, and memory pointed by bstrMsg is freed by _bstr_t destructor.
Thus in next line bstrMsg is just a dangling pointer. This is why you
have crash.

Instead you should just use:

_bstr_t bstrtMsg = m_pFINMsg->getMsg();

If, on the other hand, getMsg() is not a wrapper and is *really*
returning a BSTR (not _bstr_t ), then you have a memory leak (but then
program wouldn't crash). Initialization of _bstr_t from BSTR will make a
copy and NOT take ownership of the string, unless you pass false as
second argument of constructor (that is fCopy, as documented in MSDN) -
in which case _bstr_t will take ownership of returned BSTR. If you just
use implicit conversion from BSTR to _bstr_t, you actually make a copy
of BSTR returned by COM function (instead of taking ownership), probably
no-one will free this BSTR and you have a leak.
STDMETHODIMP CFINMsg::getMsg(BSTR * o_Msg)
{
--------------------------------
-----------------------------
*o_Msg = m_OGMsg.copy(); //m_OGMsg is declared as _bstr_t
return S_OK;


If your function is returning a string (that is "[OUT, RETVAL] BSTRT *"
), you should pass ownership of _bstr_t . For this operation use
Detach(), not copy(). It's not that copy() or copy(true) are bad (they
aren't), but if you happen to call by mistake copy(false) or just
perform implicit converion from _bstr_t to BSTR, you will again end up
with dangling pointer. On the other hand, copy(true) is safe, but is
also wasting CPU cycles, as it allocates new string unnecessarily.
Obviously, caller of your function is resposible for freeing BSTR
returned as [OUT, RETVAL], but this is mandated by COM and provided by
COM wrappers (that is #import , *.tlh and *.tli files) so you do not
have to worry - if you use these COM wrappers properly.

I suggest that you buy this book
http://www.amazon.com/gp/product/0735611270/ (and I mean this one, not
any other - it's out of print, but there are still copies available) and
read first 3 chapters very, very carefully. At least twice. You would
benefit from other good books on COM, too.
B.
PS. some samples:

#include <comdef.h>

// fragile, caller might leak returned BSTR
BSTR foo() {_bstr_t t = L"foo"; return t.Detach();}

// fragile and unnecessary overhead making a copy
BSTR bar() {_bstr_t t = L"bar"; return t.copy();}

// very bad, returning dangling pointer
BSTR boo() {_bstr_t t = L"boo"; return t.copy(false);}

// very bad, just like boo, as operator BSTR is equiv. to copy(false)
BSTR bam() {_bstr_t t = L"bam"; return t;}

// reliable, like code provided by COM wrappers
_bstr_t bow() {_bstr_t t = L"bow"; return t;}

int main()
{
_bstr_t t(foo(), false); // OK, but fragile
_bstr_t t1 = bar(); // memory leak!
_bstr_t t2 = boo(); // crash!
_bstr_t t3 = bam(); // crash!
_bstr_t t4 = bow(); // OK and reliable
BSTR t5 = bow(); // potential trap ...
_bstr_t t6 = t5; // ... and crash!
}
obviusly, actual crash might or might not happen, depending on compiler
version, compilation options, sorrounding code etc - using dangling
pointer is always bad, however it may not always result in immediate
crash - often you will just see "bad" results, and sometimes you will
not even notice that you have a problem. This especially applies to
small sample app. that actually does nothing, just like the one above.

Mar 14 '06 #4
B. wrote:
Instead you should just use:

_bstr_t bstrtMsg = m_pFINMsg->getMsg();


The code was changed to capture the BSTR into a _bstr_t wrapper and
application(s) works as expected - from what was seen in our initial
tests. The code extract that was changed is below -

const string FMLMsgProxy::getMsg ()
{
//BSTR bstrMsg = m_pFINMsg->getMsg(); // the code before
_bstr_t bstrtMsg = m_pFINMsg->getMsg(); // code after change
-------------------
--------------
}

Thanks a million ton for the informational post.

Sunita

Mar 15 '06 #5
su**************@gmail.com wrote:
//BSTR bstrMsg = m_pFINMsg->getMsg(); // the code before
_bstr_t bstrtMsg = m_pFINMsg->getMsg(); // code after change
good.
Thanks a million ton for the informational post.


you are welcome. Pardon my conceited tone, but I suggest that you review
whole application seeking for similar mistakes. Regards
B.
Mar 15 '06 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: Karthik | last post by:
Hello, How can I convert a BSTR data type to std::string??? Thanks a much! Karthik
2
by: banski | last post by:
Hi, Im trying to find out how to convert a SYSTEMTIME to BSTR. Cant find out how to do that. Hopefully some of you could help me out. Best regards Thomas
7
by: Gilad Walden | last post by:
I use C# in .NET framework. I have an ActiveX implemented in C++ that has a COM interface method that gets as it’s out parameter a BSTR* . The interop translates this BSTR* into C# string. From...
0
by: Digifox | last post by:
Below is a class method that puts a new string in place of the old one! I am new to this environment! But if I am in the write area to begin with! I am trying to iterate thru the string passed...
0
by: Digifox | last post by:
I am new to this environment! But if I am in the write area to begin with! In my atl dll I am creating a functions that pass information back and forth to access, vb and csharp. I am trying to...
10
by: Robert | last post by:
I have an app that was originally 1.1, now migrated to 2.0 and have run into some sporadic viewstate errors...usually saying the viewstate is invalid, eventvalidation failed or mac error. My web...
4
by: joseph_mueller | last post by:
I have a BSTR something like this firstHalf.secondHalf I want to parse this string using the "." as the delimeter, so I will end up with two different BSTRs, one for the stuff before the "."...
4
by: Abubakar | last post by:
Hi, Lets say I write this line: BSTR b = m_pdoc->Getxml (); where m_pdoc is MSXML2::IXMLDOMDocumentPtr. Now "b" contains the xml text. When I exit the function in which this line is written,...
2
by: Lucy Ludmiller | last post by:
How can I write a function like this: BSTR Greeting(BSTR name) { //return "Good Morning : " + name ; } In short I'm looking for a quick tutorial on using BSTR - Google is not bringing up...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.