Announcement

Collapse
No announcement yet.

Trying New GlobalMem Functions; Problems With Releasing Memory

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Trying New GlobalMem Functions; Problems With Releasing Memory

    Today I got adventurous and decided to learn a new PowerBASIC statement - Type Set. New for me anyway! All I wanted to do was find the simplest way to copy the members of a type from one instance to another without having to do a member by member copy - and that is definitely the way to do it.

    Emboldened by my success at this rather advanced achievement I figured I'd give PowerBASIC's new GlobalMem Alloc/Free a try. What I needed to do was copy data from a type to another type of the exact same kind but the latter type would be in allocated memory and I'd be using a 'type ptr'. I can't seem to get the memory to free when I do this. Here is my first example with the output afterwards...

    Code:
    #Compile Exe
    #Dim All
    
    Type First
      a As Long
      b As Long
      c As Long
    End Type
    
    Type Second
      a As Long
      b As Long
      c As Long
    End Type
    
    Type Third
      a As Long
      b As Long
      c As Long
    End Type
    
    Function PBMain() As Long
      Local here As First
      Local there As Second
      Local everywhere As Third Ptr
      Local iRet As Long
      Local dwVar As Dword
    
      here.a=1 : here.b=2 : here.c=3
      Type Set there=here
      Print here.a,        here.b,        here.c
      Print there.a,       there.b,       there.c
      Print "Sizeof(Third) = " Sizeof(Third)
      GlobalMem Alloc Sizeof(Third) To dwVar
      everywhere=dwVar
      Print "dwVar      = " dwVar
      Print "everywhere = " everywhere
      Type Set @everywhere=there
      Print @everywhere.a, @everywhere.b, @everywhere.c
      GlobalMem Free dwVar To iRet
      Print "iRet = " iRet
      Waitkey$
    
      PBMain=0
    End Function
    Output from above
    Code:
     1             2             3
     1             2             3
    Sizeof(Third) =  12
    dwVar      =  8519684
    everywhere =  8519684
     1             2             3
    iRet =  8519684
    As you can see iRet is the return PowerBASIC provides for the memory de-allocation and from the docs it follows the standard convention of using zero as a successful release. Note that the Type Set statement was successful in copying the TYPE data to the template in memory.

    According to the docs the variable after the 'To' in the GlobalMem statement can only be a LONG or DWORD, and that is what I used above. Below, however, is another iteration of the program where I simply did away with the dwPtr variable and told GlobalMem to just put the memory directly in an everywhere variable of TYPE Third. It actually works but the memory doesn't release as in the 1st example...

    Code:
    #Compile Exe
    #Dim All
    
    Type First
      a As Long
      b As Long
      c As Long
    End Type
    
    Type Second
      a As Long
      b As Long
      c As Long
    End Type
    
    Type Third
      a As Long
      b As Long
      c As Long
    End Type
    
    Function PBMain() As Long
      Local here As First
      Local there As Second
      Local everywhere As Third Ptr
      Local iRet As Long
    
      here.a=1 : here.b=2 : here.c=3
      Type Set there=here
      Print here.a,        here.b,        here.c
      Print there.a,       there.b,       there.c
      Print "Sizeof(Third) = " Sizeof(Third)
      GlobalMem Alloc Sizeof(Third) To everywhere
    
      Type Set @everywhere=there
      Print @everywhere.a, @everywhere.b, @everywhere.c
      GlobalMem Free everywhere To iRet
      Print "iRet = " iRet
      Waitkey$
    
      PBMain=0
    End Function
    This works quite good, but doesn't release the memory either. Finally I tried an example with just 32 bit numbers and that is the only example I was able to get to work...

    Code:
    #Compile Exe
    #Dim All
    
    Function PBMain() As Long
      Register i As Long
      Local dwPtr As Dword Ptr
    
      GlobalMem Alloc 16*Sizeof(dwPtr) To dwPtr
      Print "dwPtr = " dwPtr  : Print
      For i=0 To 15
        @dwPtr[i]=i
      Next i
      For i=0 To 15
        Print i, Varptr(@dwPtr[i]), @dwPtr[i]
      Next i
      Print
      GlobalMem Free dwPtr To dwPtr
      Print "dwPtr = " dwPtr
      Waitkey$
    
      PBMain=0
    End Function
    
    'dwPtr =  8519684
    '
    ' 0             8519684       0
    ' 1             8519688       1
    ' 2             8519692       2
    ' 3             8519696       3
    ' 4             8519700       4
    ' 5             8519704       5
    ' 6             8519708       6
    ' 7             8519712       7
    ' 8             8519716       8
    ' 9             8519720       9
    ' 10            8519724       10
    ' 11            8519728       11
    ' 12            8519732       12
    ' 13            8519736       13
    ' 14            8519740       14
    ' 15            8519744       15
    '
    'dwPtr =  0
    This is leaving me with the impression I ought to stick to my trusty old Api calls as this new statement doesn't seem to work well with user defined types??? What am I doing wrong?
    Fred
    "fharris"+Chr$(64)+"evenlink"+Chr$(46)+"com"

  • #2
    This Still Works...

    Code:
    #Compile Exe
    #Dim All
    #Include "Win32Api.inc"
    
    Type First
      a As Long
      b As Long
      c As Long
    End Type
    
    Type Second
      a As Long
      b As Long
      c As Long
    End Type
    
    Function PBMain() As Long
      Local here As First
      Local ptrSecond As Second Ptr
      Local blnFree As Long
      
      here.a=1 : here.b=2 : here.c=3
      Print here.a,        here.b,        here.c
      Print "Sizeof(Second) = " Sizeof(Second)
      ptrSecond=GlobalAlloc(%GPTR,Sizeof(Second))
      Print "ptrSecond      = " ptrSecond
      Type Set @ptrSecond=here
      Print @ptrSecond.a, @ptrSecond.b, @ptrSecond.c
      blnFree=GlobalFree(ptrSecond)
      Print "blnFree        = " blnFree "zero (0) is success"
      Waitkey$
    
      PBMain=0
    End Function

    Output
    ==============================
    Code:
     1             2             3
    Sizeof(Second) =  12
    ptrSecond      =  1347368
     1             2             3
    blnFree        =  0 zero (0) is success
    Fred
    "fharris"+Chr$(64)+"evenlink"+Chr$(46)+"com"

    Comment


    • #3
      Specifying what compiler to try it on, its a good way to encourage
      others to test your code.

      Comment


      • #4
        Yes, you're right Elias. In the heat of playing with it I forgot. Its PB CC 50. I usually experiment with that.
        Fred
        "fharris"+Chr$(64)+"evenlink"+Chr$(46)+"com"

        Comment


        • #5
          Fred, I'm getting a kernel page fault that seems to be caused by
          Code:
            TYPE SET @everywhere=there
          so subsequent statements might not function correctly due to that. But I haven't figured out yet why this line fails.

          Comment


          • #6
            More Succinct Code

            Below is a more succinct coding of the issue, but other than that it doesn't add anything new. I appreciate you're looking at it John.

            You think the issue is with the Type Set rather than the GlobalMem? Please say no! I've been programming with PowerBASIC for about ten years and whenever I want to transfer data between two of the same types of UDT I do a member by member assignment, all the while thinking "Why don't I do a memcpy or some other kind of low level fancy trick to save myself the typing instead of being such a drudge?" But I never do and just go on typing. Today I finally decided to research the issue and bingo! Type Set!

            Well, if it isn't supposed to be able to copy data to a location pointed to by a pointer I don't suspect I'll use it, because I use pointers a real lot. I will say this though. In about an hour this afternoon I incorporeated it into an app of mine I'm working on, and it seems to be working fine there. I wasn't using GlobalMem though, but rather the Win Api GlobalAlloc().

            Code:
            #Compile Exe
            #Dim All
            
            Type First
              a As Long
              b As Long
              c As Long
            End Type
            
            Type Second
              a As Long
              b As Long
              c As Long
            End Type
            
            Function PBMain() As Long
              Local here As First
              Local ptrSecond As Second Ptr
              Local blnFree As Long
            
              here.a=1 : here.b=2 : here.c=3
              Print "here.a         = " here.a
              Print "here.b         = " here.b
              Print "here.c         = " here.c  : Print
              Print "Sizeof(Second) = " Sizeof(Second)
              GlobalMem Alloc Sizeof(Second) To ptrSecond
              Print "ptrSecond      = " ptrSecond
              Type Set @ptrSecond=here
              Print "@ptrSecond.a   = " @ptrSecond.a
              Print "@ptrSecond.b   = " @ptrSecond.b
              Print "@ptrSecond.c   = " @ptrSecond.c
              GlobalMem Free ptrSecond To blnFree
              Print "blnFree        = " blnFree " That's " blnFree "More Than One Wants To See!"
              Waitkey$
            
              PBMain=0
            End Function
            Output
            Code:
            here.a         =  1
            here.b         =  2
            here.c         =  3
            
            Sizeof(Second) =  12
            ptrSecond      =  13303812
            @ptrSecond.a   =  1
            @ptrSecond.b   =  2
            @ptrSecond.c   =  3
            blnFree        =  13303812  That's  13303812 More Than One Wants To See!
            Last edited by Fred Harris; 8 Jan 2009, 09:15 PM. Reason: add some humor!
            Fred
            "fharris"+Chr$(64)+"evenlink"+Chr$(46)+"com"

            Comment


            • #7
              Eliminate Type Set

              Here's a version without Type Set - just a member by member assignment - and it fails too.

              Code:
              #Compile Exe
              #Dim All
              
              Type First
                a As Long
                b As Long
                c As Long
              End Type
              
              Type Second
                a As Long
                b As Long
                c As Long
              End Type
              
              Function PBMain() As Long
                Local here As First
                Local ptrSecond As Second Ptr
                Local blnFree As Long
              
                here.a=1 : here.b=2 : here.c=3
                Print "here.a         = " here.a
                Print "here.b         = " here.b
                Print "here.c         = " here.c  : Print
                Print "Sizeof(Second) = " Sizeof(Second)
                GlobalMem Alloc Sizeof(Second) To ptrSecond
                Print "ptrSecond      = " ptrSecond
                'Type Set @ptrSecond=here
                @ptrSecond.a=here.a
                @ptrSecond.b=here.b
                @ptrSecond.c=here.c
                Print "@ptrSecond.a   = " @ptrSecond.a
                Print "@ptrSecond.b   = " @ptrSecond.b
                Print "@ptrSecond.c   = " @ptrSecond.c
                GlobalMem Free ptrSecond To blnFree
                Print "blnFree        = " blnFree
                Print
                Print "That's " blnFree "More Than One Wants To See!"
                Waitkey$
              
                PBMain=0
              End Function
              
              'here.a         =  1
              'here.b         =  2
              'here.c         =  3
              '
              'Sizeof(Second) =  12
              'ptrSecond      =  13303812
              '@ptrSecond.a   =  1
              '@ptrSecond.b   =  2
              '@ptrSecond.c   =  3
              'blnFree        =  13303812
              '
              'That's  13303812 More Than One Wants To See!
              Fred
              "fharris"+Chr$(64)+"evenlink"+Chr$(46)+"com"

              Comment


              • #8
                Last Try

                Here's a version strictly by the books that doesn't use Type Set and uses a DWORD to receive the virtual memory handle.

                Code:
                #Compile Exe
                #Dim All
                
                Type First
                  a As Long
                  b As Long
                  c As Long
                End Type
                
                Type Second
                  a As Long
                  b As Long
                  c As Long
                End Type
                
                Function PBMain() As Long
                  Local here As First
                  Local ptrSecond As Second Ptr
                  Local blnFree As Long
                  Local dwPtr As Dword
                  
                  here.a=1 : here.b=2 : here.c=3
                  Print "here.a         = " here.a
                  Print "here.b         = " here.b
                  Print "here.c         = " here.c  : Print
                  Print "Sizeof(Second) = " Sizeof(Second)
                  GlobalMem Alloc Sizeof(Second) To dwPtr
                  ptrSecond=dwPtr
                  Print "ptrSecond      = " ptrSecond
                  @ptrSecond.a=here.a
                  @ptrSecond.b=here.b
                  @ptrSecond.c=here.c
                  Print "@ptrSecond.a   = " @ptrSecond.a
                  Print "@ptrSecond.b   = " @ptrSecond.b
                  Print "@ptrSecond.c   = " @ptrSecond.c
                  GlobalMem Free dwPtr To blnFree
                  Print "blnFree        = " blnFree
                  Print
                  Print "That's " blnFree "More Than One Wants To See!"
                  Waitkey$
                
                  PBMain=0
                End Function
                
                'here.a         =  1
                'here.b         =  2
                'here.c         =  3
                '
                'Sizeof(Second) =  12
                'ptrSecond      =  13303812
                '@ptrSecond.a   =  1
                '@ptrSecond.b   =  2
                '@ptrSecond.c   =  3
                'blnFree        =  13303812
                '
                'That's  13303812 More Than One Wants To See!
                Fred
                "fharris"+Chr$(64)+"evenlink"+Chr$(46)+"com"

                Comment


                • #9
                  Well, Fred, the secret to success here is to review the documentation. The block of memory allocated by GLOBALMEM is movable memory. The value returned by GLOBALMEM ALLOC is not a pointer, it is a handle, but you incorrectly used it as a pointer. The correct sequence is:

                  1- Allocate memory and get a handle
                  2- Lock memory referenced by the handle and get a pointer to it.
                  3- Use the pointer
                  4- Unlock the memory
                  5- Free the memory block

                  Any other sequence is doomed to fail.

                  Bob Zale
                  PowerBASIC Inc.

                  Comment


                  • #10
                    Problem Solved! Thanks Bob!
                    Fred
                    "fharris"+Chr$(64)+"evenlink"+Chr$(46)+"com"

                    Comment


                    • #11
                      Fred,

                      No fair teasing. Would you post the changes that worked?

                      Comment


                      • #12
                        >Would you post the changes that worked?
                        Code:
                           Local everywhere As Third Ptr
                            ...
                           GlobalMem Alloc Sizeof(Third) To everywhere
                         
                            Type Set @everywhere=there
                        ===>
                        Code:
                           Local everywhere As Third Ptr
                            ...
                           GlobalMem Alloc Sizeof(Third) To [COLOR="Red"]hMem
                           GLOBALMEM LOCK  hMem TO  everywhere[/COLOR]
                           Type Set @everywhere=there
                           [COLOR="Red"]GLOBALMEM UNLOCK hMem TO uselessvar[/COLOR]
                        MCM
                        Michael Mattias
                        Tal Systems (retired)
                        Port Washington WI USA
                        [email protected]
                        http://www.talsystems.com

                        Comment

                        Working...
                        X