Solved

When to use SysFreeString on a BSTR?

Posted on 1998-07-13
4
4,109 Views
Last Modified: 2012-06-21
We are developing 32 bit Automation components using VB 5.0 and MFC ClassWizard.  On our components we have several accessor methods that manipulate a CString and then return a BSTR back to the consumer by using the AllocSysString() method:

BSTR SomeClass::getSomeString()
{
   CString strResult;

   strResult = "Something.."

   return ( strResult.AllocSysString();
}

The consumer would use a smart pointer to a SomeClass instance to access this function like this:

{
// create smart pointer
   _DSomeClassPtr   anObject;
anObject.CreateInstance(SOME_CLASS_NAME);

// get the string
BSTR  aBSTRString;
aBSTRString = anObject->getSomeString()

//  do something with it, like convert back to a CString
CString strResult;
strResult = CString(aString);

// Free the BSTR... Is this necessary?
::SysFreeString(aBSTRString)
}

BoundsChecker flags an error indicating the SysFreeString is freeing memory in a bad address location.  

The MSDN indicates that you should use ::SysFreeString in the rare case that you need to deallocate the returned string.  Should we not be using this function on BSTR's converted from CStrings using the CString::AllocSysString method?

Thanks
-R
0
Comment
Question by:rcasiple
  • 2
  • 2
4 Comments
 
LVL 11

Expert Comment

by:mikeblas
Comment Utility
Exactly what constructor are you trying to invoke when you pass a BSTR to CString::CString()?  CString has no BSTR constructor.  You should be calling CString::SetSysString().

B ekiM

0
 
LVL 3

Accepted Solution

by:
Norbert earned 50 total points
Comment Utility
First Reading the online help SetSasString will not wor in your case because it is used to set a BSTR not to get it:
CString::SetSysString

BSTR SetSysString( BSTR* pbstr ) const;

Return Value

The new string.

Parameters

pbstr   A pointer to a character string.

Remarks

Reallocates the BSTR pointed to by pbstr and copies the contents of the CString object into it, including the NULL character. The value of the BSTR referenced by pbstr may change. The function throws a CMemoryException if insufficient memory exists.

This function is normally used to change the value of strings passed by reference for OLE Automation.

Now to your problem:
I have figured out for my self - that means may be I am not right- that BSTR should be freed.
I believe that the writer about SysFreeString only had a look from C++ to VB where VB will delete the string.
But you can simple try it:
make a app that as fast as possible gets a string in a endless loop and watch the memory.
It can may be done by system monitor to watch free memory, size of swap file, used inside swapfile - Sorry I have a German version and I do not know the Exact translations used by sysmon.
If free mmory continuesly shrinks and Swapfile grows you must use SysFreeString
0
 
LVL 11

Expert Comment

by:mikeblas
Comment Utility
You're all wet on this one, Norbert.

I suggested using SetSysString() instead of the incorrect constructor invocation rcaspile was using.  It's not a solution to the question he posted, but the code he posted is dead wrong and he needs to know that.

Second, a system string has a life just like any other allocated memory that's passed from module to module. The caller must know if the callee is going to do free the string, or if the callee is going to copy the string.  Normally, in almost all circumstances, OLE Automation interfaces will have the callee own the string--therefore, the callee is responsible for freeing the string.

Your loop test is orthogonal. It's just allocating memory over and over. Of course, since nobody is being called, the ownership of the memory doesn't change. Since the loop doesn't free, the memory is leaked.

B ekiM


0
 
LVL 3

Expert Comment

by:Norbert
Comment Utility
Mikeblas: The memory is leaked only if the client (the callee) does not free it. If you are using VB as Client VB will free the memory inside its runtime. If you use C++ as client you have to free it your self.

Again about SetSysString:
I know that you did not give a solution for the problem but as I read the online help SetSysString is used to fill a BSTR with the contens of a CString not to fill a CString with the contens of a BSTR so what you suggest will not work absolutely
The best way to convert a BSTR to a CString is as I think the function
void AFXAPI AfxBSTR2CString(CString* pStr, BSTR bstr);
There is no description in online help.
the prototype is in AFXPRIV2.h and the implementation in OLECNVRT.CPP.
AFXPRIV2.H is included by AFXPRIV.h

0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Often, when implementing a feature, you won't know how certain events should be handled at the point where they occur and you'd rather defer to the user of your function or class. For example, a XML parser will extract a tag from the source code, wh…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now