Board index » cppbuilder » problem returning >64K BSTR in COM method...

problem returning >64K BSTR in COM method...

The problem I seem to be having is that data > 64K in a BSTR will not return
to the client.  To make matters worse it causes a mem leak in the COM
server.  This is my method:

STDMETHODIMP TWCOMRequestManagerImpl::Peek(BSTR* data)
{
    String temp;
    WideString buff;

    try
    {
     temp = Interface->Peek();
        if(temp.Length() > 60000)
         temp = temp.SubString(1, 60000);
     buff = temp;
     *data = buff;
    }
 catch(Exception &e)
 {
     return Error(e.Message.c_str(), IID_IWCOMRequestManager);
    }

 return S_OK;

Quote
}

You can see that I added code to truncate the data, but this is a very bad
hack!  Is this a known problem?

Thanks...

John.

 

Re:problem returning >64K BSTR in COM method...


One problem I see is that you're not calling Detach() at all.  You need to
do that.  Otherwise, when the WideString goes out of scope, it frees the
string data and the memory becomes corrupted by the time the caller tries to
use it.

As per the COM specs, when you return a BSTR to the caller, the caller is
supposed to take ownership of the data memory, and it becomes the caller's
responsibility to free the memory later.  The callee is not supposed to hold
on to the memory.  But that is exactly what you're doing.

Try this instead:

    STDMETHODIMP TWCOMRequestManagerImpl::Peek(BSTR* data)
    {
        try
        {
            *data = WideString(Interface->Peek()).Detach();
        }
        catch(Exception &e)
        {
            return Error(e.Message.c_str(), IID_IWCOMRequestManager);
        }

         return S_OK;
    }

Gambit

Quote
"John" <j...@hotmail.com> wrote in message news:3cfcd77a$1_2@dnews...
> The problem I seem to be having is that data > 64K in a BSTR will not
> return to the client.  To make matters worse it causes a mem leak in the
> COM server.

Re:problem returning >64K BSTR in COM method...


Gambit,

My COM object is out of process.  How can the caller clean up the mem, it is
another process?  Or does windows hide all of that from me?

Thanks...

John.

"Remy Lebeau [TeamB]" <gambi...@yahoo.com> wrote in message
news:3cfcfce8$1_1@dnews...

Quote
> One problem I see is that you're not calling Detach() at all.  You need to
> do that.  Otherwise, when the WideString goes out of scope, it frees the
> string data and the memory becomes corrupted by the time the caller tries
to
> use it.

> As per the COM specs, when you return a BSTR to the caller, the caller is
> supposed to take ownership of the data memory, and it becomes the caller's
> responsibility to free the memory later.  The callee is not supposed to
hold
> on to the memory.  But that is exactly what you're doing.

> Try this instead:

>     STDMETHODIMP TWCOMRequestManagerImpl::Peek(BSTR* data)
>     {
>         try
>         {
>             *data = WideString(Interface->Peek()).Detach();
>         }
>         catch(Exception &e)
>         {
>             return Error(e.Message.c_str(), IID_IWCOMRequestManager);
>         }

>          return S_OK;
>     }

> Gambit

> "John" <j...@hotmail.com> wrote in message news:3cfcd77a$1_2@dnews...
> > The problem I seem to be having is that data > 64K in a BSTR will not
> > return to the client.  To make matters worse it causes a mem leak in the
> > COM server.

Re:problem returning >64K BSTR in COM method...


Quote
"John" <j...@hotmail.com> wrote in message news:3cfcffaf$1_2@dnews...
> Gambit,

> My COM object is out of process.  How can the caller clean up the mem, it
is
> another process?  Or does windows hide all of that from me?

> Thanks...

Your caller is actually a proxy running in-process, who handles all the
marshalling of data across the process boundary.

Don't know if that's the cause of your 64K limit.  I would try it in-process
and find out.

--
-- Early Ehlinger CEO, ResPower Inc - 256-533-1090 --
- RenderFarm - Lightwave,3dSMax,Bryce @$0.50/CPU*Hr -
- www.respower.com Coming Soon - Maya @$0.75/CPU*Hr -
----------- SuperComputing For the Masses! ----------
"I'm so busy programming my computer to let me be lazy, I never get any
rest!" - John Kaster

Re:problem returning >64K BSTR in COM method...


Welcome to the world of COM programming :-)

Gambit

Quote
"John" <j...@hotmail.com> wrote in message news:3cfcffaf$1_2@dnews...
> My COM object is out of process.  How can the caller clean up
> the mem, it is another process?  Or does windows hide all of that from me?

Re:problem returning >64K BSTR in COM method...


As Early Ehlinger already mentioned, when you create an instance of a COM
object, you're actually creating an local in-process proxy and working with
the proxy, not the real COM object directly.  That object does physically
reside in the out-of-process server, yes, but it's the proxy, but your
actual code itself, that handles the interactions with it.

Gambit

"Remy Lebeau [TeamB]" <gambi...@yahoo.com> wrote in message
news:3cfd1dab$1_1@dnews...

Quote
> Welcome to the world of COM programming :-)

Re:problem returning >64K BSTR in COM method...


Gambit,

The code works a lot better when its written correctly!  The detach did the
trick, the scary thing is that code has been running in our production env
for about a year and a half.

I under stand the COM proxy idea, but my question was will the COM server
clean up the BSTR I just detached?  The BSTR is now out my scope, so I'm
hoping it gets cleaned up after its packaged up and sent to the client.  On
the client side I'm doing this:

String temp2;
WideString temp = "";

//My COM call...
WCOMRequestManager->Peek(&temp);

temp2 = temp;
temp = "";

Will WideString automatically clean up the client side BSTR?

Thanks for the help...

John.

"Remy Lebeau [TeamB]" <gambi...@yahoo.com> wrote in message
news:3cfd2024_2@dnews...

Quote
> As Early Ehlinger already mentioned, when you create an instance of a COM
> object, you're actually creating an local in-process proxy and working
with
> the proxy, not the real COM object directly.  That object does physically
> reside in the out-of-process server, yes, but it's the proxy, but your
> actual code itself, that handles the interactions with it.

> Gambit

> "Remy Lebeau [TeamB]" <gambi...@yahoo.com> wrote in message
> news:3cfd1dab$1_1@dnews...
> > Welcome to the world of COM programming :-)

Re:problem returning >64K BSTR in COM method...


Cool, thank you very much...

John.

"Remy Lebeau [TeamB]" <gambi...@yahoo.com> wrote in message
news:3cfd36e7_1@dnews...

Quote

> "John" <j...@hotmail.com> wrote in message news:3cfd22cc_1@dnews...

> > I under stand the COM proxy idea, but my question was will the COM
> > server clean up the BSTR I just detached?

> No, it's not supposed to.  That's the point.  COM will marshal the memory
to
> the client and it's then the client's responsibility to free it, not the
> server.

> Memory management works differently in COM then normal programming.

> > Will WideString automatically clean up the client side BSTR?

> With the way that you're using it, yes.  The WideString correctly takes
> ownership of the BSTR and will free it when the WideString goes out of
> scope.

> Just FYI, you don't need to set the WideString to "":

>     String temp2;
>     WideString temp;

>     WCOMRequestManager->Peek(&temp);
>     temp2 = temp;

> Gambit

Re:problem returning >64K BSTR in COM method...


Quote
"John" <j...@hotmail.com> wrote in message news:3cfd22cc_1@dnews...
> I under stand the COM proxy idea, but my question was will the COM
> server clean up the BSTR I just detached?

No, it's not supposed to.  That's the point.  COM will marshal the memory to
the client and it's then the client's responsibility to free it, not the
server.

Memory management works differently in COM then normal programming.

Quote
> Will WideString automatically clean up the client side BSTR?

With the way that you're using it, yes.  The WideString correctly takes
ownership of the BSTR and will free it when the WideString goes out of
scope.

Just FYI, you don't need to set the WideString to "":

    String temp2;
    WideString temp;

    WCOMRequestManager->Peek(&temp);
    temp2 = temp;

Gambit

Other Threads