Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. COM
  4. Question about VARIANT deallocation

Question about VARIANT deallocation

Scheduled Pinned Locked Moved COM
helpquestionc++htmlcom
11 Posts 4 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • G GuimaSun

    After more than 8 hours trying to fix up a memory leak I need some help :/ I have a ATL COM component, with the following interface: STDMETHODIMP CDCSClient::CallService( VARIANT *p1 ) Inside the method I do the following: VariantClear( p ); VariantInit( p ); p->vt = VT_BSTR | VT_BYREF; BSTR *pBSTR = new BSTR; *pBSTR = SysAllocString( L"abc" ); p->pbstrVal = pBSTR; And my client in VB is like this: For i = 1 To 1000 Dim myInt As Integer myInt = 3 ret = client.CallService(myInt) Next As far as I know the COM engine is creating a VARIANT from my integer (which is received as VT_BYREF | VT_I2), and I change it to VT_BSTR. The VB loop causes a huge memory leak. Am I doing something wrong ? How the COM engine handles the new VARIANT/BSTR deallocation ? Thanks for any help.

    GuimaSun www.nexsun.com.br NEXSUN TechZone

    L Offline
    L Offline
    Lost User
    wrote on last edited by
    #2

    It seem's you might not correctly release the BSTR accociated with the VARIANT *p1 variable. You might have manually to release variant accoiated with myInt variable.

    G 1 Reply Last reply
    0
    • L Lost User

      It seem's you might not correctly release the BSTR accociated with the VARIANT *p1 variable. You might have manually to release variant accoiated with myInt variable.

      G Offline
      G Offline
      GuimaSun
      wrote on last edited by
      #3

      It was my first guess, but I don't think so...each time I receive a call (from the loop) I receive the same integer VT_BYREF | VT_I2 (which is deallocated by VariantClear). It seems that this BSTR is lost between calls, causing the leak (obviously myInt is an integer and can't reflect changes).

      GuimaSun www.nexsun.com.br NEXSUN TechZone

      L 1 Reply Last reply
      0
      • G GuimaSun

        It was my first guess, but I don't think so...each time I receive a call (from the loop) I receive the same integer VT_BYREF | VT_I2 (which is deallocated by VariantClear). It seems that this BSTR is lost between calls, causing the leak (obviously myInt is an integer and can't reflect changes).

        GuimaSun www.nexsun.com.br NEXSUN TechZone

        L Offline
        L Offline
        Lost User
        wrote on last edited by
        #4

        If the BSTR is lost why don't you use BSTR* as variable type instead of VARIANT. Which version of VB are you using?

        G 1 Reply Last reply
        0
        • L Lost User

          If the BSTR is lost why don't you use BSTR* as variable type instead of VARIANT. Which version of VB are you using?

          G Offline
          G Offline
          GuimaSun
          wrote on last edited by
          #5

          I can't change that interface, the real code is far more complicated, basically I need to receive a VARIANT* and change their value, and the new value comes from a c++ string. I'm testing using VB 6. Thanks.

          GuimaSun www.nexsun.com.br NEXSUN TechZone

          1 Reply Last reply
          0
          • G GuimaSun

            After more than 8 hours trying to fix up a memory leak I need some help :/ I have a ATL COM component, with the following interface: STDMETHODIMP CDCSClient::CallService( VARIANT *p1 ) Inside the method I do the following: VariantClear( p ); VariantInit( p ); p->vt = VT_BSTR | VT_BYREF; BSTR *pBSTR = new BSTR; *pBSTR = SysAllocString( L"abc" ); p->pbstrVal = pBSTR; And my client in VB is like this: For i = 1 To 1000 Dim myInt As Integer myInt = 3 ret = client.CallService(myInt) Next As far as I know the COM engine is creating a VARIANT from my integer (which is received as VT_BYREF | VT_I2), and I change it to VT_BSTR. The VB loop causes a huge memory leak. Am I doing something wrong ? How the COM engine handles the new VARIANT/BSTR deallocation ? Thanks for any help.

            GuimaSun www.nexsun.com.br NEXSUN TechZone

            S Offline
            S Offline
            Stuart Dootson
            wrote on last edited by
            #6

            I suspect that rather than 'new BSTR', you should use CoTaskMemAlloc[^] to allocate memory in a COM server:

            BSTR *pBSTR = (BSTR*)CoTaskMemAlloc(sizeof(BSTR));

            However - one other thing strikes me - why pass the BSTR back by reference? Why not use this?

            VariantClear( p );
            VariantInit( p );
            p->vt = VT_BSTR;
            p->pbstrVal = SysAllocString( L"abc" );

            One less allocation, one less place to leak memory!

            Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

            G 1 Reply Last reply
            0
            • S Stuart Dootson

              I suspect that rather than 'new BSTR', you should use CoTaskMemAlloc[^] to allocate memory in a COM server:

              BSTR *pBSTR = (BSTR*)CoTaskMemAlloc(sizeof(BSTR));

              However - one other thing strikes me - why pass the BSTR back by reference? Why not use this?

              VariantClear( p );
              VariantInit( p );
              p->vt = VT_BSTR;
              p->pbstrVal = SysAllocString( L"abc" );

              One less allocation, one less place to leak memory!

              Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

              G Offline
              G Offline
              GuimaSun
              wrote on last edited by
              #7

              Hi The same happens with CoTaskMemAlloc, and using VT_BSTR instead of VT_BSTR | VT_BYREF. Thanks anyway.

              GuimaSun www.nexsun.com.br NEXSUN TechZone

              1 Reply Last reply
              0
              • G GuimaSun

                After more than 8 hours trying to fix up a memory leak I need some help :/ I have a ATL COM component, with the following interface: STDMETHODIMP CDCSClient::CallService( VARIANT *p1 ) Inside the method I do the following: VariantClear( p ); VariantInit( p ); p->vt = VT_BSTR | VT_BYREF; BSTR *pBSTR = new BSTR; *pBSTR = SysAllocString( L"abc" ); p->pbstrVal = pBSTR; And my client in VB is like this: For i = 1 To 1000 Dim myInt As Integer myInt = 3 ret = client.CallService(myInt) Next As far as I know the COM engine is creating a VARIANT from my integer (which is received as VT_BYREF | VT_I2), and I change it to VT_BSTR. The VB loop causes a huge memory leak. Am I doing something wrong ? How the COM engine handles the new VARIANT/BSTR deallocation ? Thanks for any help.

                GuimaSun www.nexsun.com.br NEXSUN TechZone

                V Offline
                V Offline
                Vi2
                wrote on last edited by
                #8

                How CallService is defined in IDL file? If it's "CallService([in] VARIANT *p1)", then you cannot change the parameter. If it's "CallService([in,out] VARIANT *p1), then you cannot receive the parameter in Integer. IAC, VB passes myInt variable as VT_BYREF | VT_I2 to be possible to change the myInt value. It's made only during call some method. Inside VB don't store variant by this manner. STDMETHODIMP CDCSClient::CallService( VARIANT *p ) { VariantClear( p ); p->vt = VT_BSTR; p->bstrVal = SysAllocString( L"abc" ); return S_OK; } If you desire to pass BSTR by reference, you should keep out this address and make sure to free this BSTR after using. BSTR g_pBSTR = NULL; // global scope, so somewhere should be "if (!g_pBSTR) SysFreeString(g_pBSTR);" STDMETHODIMP CDCSClient::CallService( VARIANT *p ) { VariantClear( p ); p->vt = VT_BSTR | VT_BYREF; if (!g_pBSTR) g_pBSTR = SysAllocString( L"abc" ); p->pbstrVal = &g_pBSTR; return S_OK; }

                With best wishes, Vita

                G 1 Reply Last reply
                0
                • V Vi2

                  How CallService is defined in IDL file? If it's "CallService([in] VARIANT *p1)", then you cannot change the parameter. If it's "CallService([in,out] VARIANT *p1), then you cannot receive the parameter in Integer. IAC, VB passes myInt variable as VT_BYREF | VT_I2 to be possible to change the myInt value. It's made only during call some method. Inside VB don't store variant by this manner. STDMETHODIMP CDCSClient::CallService( VARIANT *p ) { VariantClear( p ); p->vt = VT_BSTR; p->bstrVal = SysAllocString( L"abc" ); return S_OK; } If you desire to pass BSTR by reference, you should keep out this address and make sure to free this BSTR after using. BSTR g_pBSTR = NULL; // global scope, so somewhere should be "if (!g_pBSTR) SysFreeString(g_pBSTR);" STDMETHODIMP CDCSClient::CallService( VARIANT *p ) { VariantClear( p ); p->vt = VT_BSTR | VT_BYREF; if (!g_pBSTR) g_pBSTR = SysAllocString( L"abc" ); p->pbstrVal = &g_pBSTR; return S_OK; }

                  With best wishes, Vita

                  G Offline
                  G Offline
                  GuimaSun
                  wrote on last edited by
                  #9

                  The parameter is defined as [in,out,optional]. And yes, now I understand, as I suspected, I can't reallocate the VT_BYREF | VT_I2 inside my ATL code. The only thing still not 100% clear which confused me is that I can define a VB procedure receiving a byref variant, do the same thing receiving my int, and changing it to String and no leak happens. That was my first test. But the difference is: there's no COM in this scenario, and the pure VB allocation\dellocation mechanisms are not the same. Thanks a lot !

                  GuimaSun www.nexsun.com.br NEXSUN TechZone

                  V 2 Replies Last reply
                  0
                  • G GuimaSun

                    The parameter is defined as [in,out,optional]. And yes, now I understand, as I suspected, I can't reallocate the VT_BYREF | VT_I2 inside my ATL code. The only thing still not 100% clear which confused me is that I can define a VB procedure receiving a byref variant, do the same thing receiving my int, and changing it to String and no leak happens. That was my first test. But the difference is: there's no COM in this scenario, and the pure VB allocation\dellocation mechanisms are not the same. Thanks a lot !

                    GuimaSun www.nexsun.com.br NEXSUN TechZone

                    V Offline
                    V Offline
                    Vi2
                    wrote on last edited by
                    #10

                    STDMETHODIMP CDCSClient::CallService(/*[in,out]*/ VARIANT *p)
                    {
                    if (V_VT(p) == (VT_VARIANT | VT_BYREF))
                    {
                    // only here you can change the type of passed variable (see VB example below)
                    VARIANT *p2 = V_VARIANTREF(p);
                    p2->vt = VT_BSTR;
                    p2->bstrVal = SysAllocString( L"abc" );
                    return S_OK;
                    }
                    }

                    Dim v As Variant
                    v = 1
                    Debug.Print TypeName(v) & " " & v
                    Call obj.CallService(v)
                    Debug.Print TypeName(v) & " " & v

                    With best wishes, Vita

                    1 Reply Last reply
                    0
                    • G GuimaSun

                      The parameter is defined as [in,out,optional]. And yes, now I understand, as I suspected, I can't reallocate the VT_BYREF | VT_I2 inside my ATL code. The only thing still not 100% clear which confused me is that I can define a VB procedure receiving a byref variant, do the same thing receiving my int, and changing it to String and no leak happens. That was my first test. But the difference is: there's no COM in this scenario, and the pure VB allocation\dellocation mechanisms are not the same. Thanks a lot !

                      GuimaSun www.nexsun.com.br NEXSUN TechZone

                      V Offline
                      V Offline
                      Vi2
                      wrote on last edited by
                      #11

                      About memory leaks. VB allocation\dellocation mechanisms are the same with COM.

                      p->vt = VT_BSTR | VT_BYREF;
                      BSTR *pBSTR = new BSTR;
                      *pBSTR = SysAllocString( L"abc" );
                      p->pbstrVal = pBSTR;

                      There are 2 memory allocations in statements "= new BSTR" and "= SysAllocString". The VARIANT with VT_BYREF|VT_BSTR isn't an owner of its values, so freeing of the VARIANT doesn't free neither pbstrVal nor *pbstrVal. And finally you have memory leaks. The VARIANT with VT_BSTR (without VT_BYREF) is an owner of its values, so freeing of the VARIANT frees bstrVal.

                      p->vt = VT_BSTR;
                      p->bstrVal = SysAllocString( L"abc" );

                      And there are no memory leaks.

                      With best wishes, Vita

                      1 Reply Last reply
                      0
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      • Login

                      • Don't have an account? Register

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • World
                      • Users
                      • Groups