Results 1 to 18 of 18

Thread: [RESOLVED] Need Full Understanding of VarPtr, StrPtr, ObjPtr

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Aug 2011
    Location
    B.C., Canada
    Posts
    2,887

    Resolved [RESOLVED] Need Full Understanding of VarPtr, StrPtr, ObjPtr

    What exactly is a pointer? How or why is it used?
    I would like to understand what a pointer is and why using varptr, strptr, objptr can be faster at finding variants/objects and how does it work behind the code (or what exactly does it do for you).

    I hope I'm not asking too much

    I know some api(s) need you to pass it as an argument, but why?

  2. #2
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,060
    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

  3. #3

    Thread Starter
    PowerPoster
    Join Date
    Aug 2011
    Location
    B.C., Canada
    Posts
    2,887

    Re: Need Full Understanding of VarPtr, StrPtr, ObjPtr

    I was looking already at your third link Bonnie.

    So I understand this code, its simple.

    Code:
    Private Sub Command1_Click()
    Dim str1 As String
    
    str1 = vbNullString
    Debug.Print StrPtr(str1)
    
    str1 = ""
    Debug.Print StrPtr(str1)
    
    End Sub
    Now, it gave me this result (I ran it twice)

    Code:
     0 
     100327580 
     0 
     100110556
    What is this 100110556? (That would be a pointer right?)
    Where is that stored?
    Why is the number that long?
    What does it mean?

  4. #4
    PowerPoster
    Join Date
    Feb 2012
    Location
    West Virginia
    Posts
    14,205

    Re: Need Full Understanding of VarPtr, StrPtr, ObjPtr

    A pointer is basically a memory address, so that number is telling you the memory address of your empty string or at least that is my understanding of it.

  5. #5

    Thread Starter
    PowerPoster
    Join Date
    Aug 2011
    Location
    B.C., Canada
    Posts
    2,887

    Re: Need Full Understanding of VarPtr, StrPtr, ObjPtr

    Ok so to get to that address in your memory how do you access it, like mine "100110556". Where is that in my memory and how will i know how long the string is?

  6. #6
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,060

    Re: Need Full Understanding of VarPtr, StrPtr, ObjPtr

    Quote Originally Posted by Max187Boucher View Post
    What is this 100110556? (That would be a pointer right?)
    That number is the virtual memory address where the empty string ("") is located. It's actually not a pointer.

    Quote Originally Posted by Max187Boucher View Post
    Where is that stored?
    In the Random Access Memory of your PC, of course! Seriously though, the empty string is stored in the heap.

    Quote Originally Posted by Max187Boucher View Post
    Why is the number that long?
    Because in 32-bit Windows, virtual memory addresses range from &H10000 to &HFFFFFFFF.

    Quote Originally Posted by Max187Boucher View Post
    What does it mean?
    That means the empty string was allocated beginning at the virtual memory address 100110556 (&H5F790DC).


    You may want to read the Memory address article too.
    Last edited by Bonnie West; Mar 29th, 2014 at 08:00 PM.
    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

  7. #7
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,060

    Re: Need Full Understanding of VarPtr, StrPtr, ObjPtr

    Quote Originally Posted by Max187Boucher View Post
    Ok so to get to that address in your memory how do you access it, like mine "100110556".
    That's what pointers are for; they hold memory addresses (like 100110556) so you can dereference the value located at the address it points to.

    Quote Originally Posted by Max187Boucher View Post
    Where is that in my memory ...
    The empty string is most likely in the area of memory called the "heap".

    Quote Originally Posted by Max187Boucher View Post
    ... how will i know how long the string is?
    Code:
    Len(str1)
    LenB(str1)
    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

  8. #8

    Thread Starter
    PowerPoster
    Join Date
    Aug 2011
    Location
    B.C., Canada
    Posts
    2,887

    Re: Need Full Understanding of VarPtr, StrPtr, ObjPtr

    Ok let's say I only have this number "100110556", how to I get my blank string from that? Which api would I use?

  9. #9
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,060

    Re: Need Full Understanding of VarPtr, StrPtr, ObjPtr

    Quote Originally Posted by Max187Boucher View Post
    Ok let's say I only have this number "100110556", how to I get my blank string from that? Which api would I use?
    The GetStrFromPtr function here shows one possibility.
    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

  10. #10

    Thread Starter
    PowerPoster
    Join Date
    Aug 2011
    Location
    B.C., Canada
    Posts
    2,887

    Re: Need Full Understanding of VarPtr, StrPtr, ObjPtr

    Also I was messing around with copymemory and globalfree(lock/unlock) api

    so I tried to use long arrays instead from this example, not sure if I did it right but it works

    Code:
    Dim s(0 To 255) As Integer, t(0 To 255) As Integer ' arrays to copy from/to
    Dim c As Integer, retval As Long ' counter variable & return value
    Dim hMem As Long, pMem As Long ' handle and pointer to memory block
    
    ' Initialize the source array s()'s data
    For c = 0 To 255
    s(c) = 2 * c ' each element equals double its index
    Next c
    
    ' Allocate a moveable block of memory (returns a handle) (Integer type = 2 bytes)
    hMem = GlobalAlloc(GMEM_MOVEABLE Or GMEM_ZEROINIT, 256 * 2)
    ' Lock the memory block, returning a pointer to it
    pMem = GlobalLock(hMem)
    ' Copy the entire contents of s() to the memory block
    ' Note that pMem is ByVal because we want its contents, not a pointer to it
    CopyMemory ByVal pMem, s(0), 256 * 2
    ' Copy the contents of the memory block to t() (we could have just copied s() to t())
    CopyMemory t(0), ByVal pMem, 256 * 2
    ' Unlock the memory block, destroying the pointer and freeing resources
    x = GlobalUnlock(hMem)
    ' Free the memory block (de-allocate it)
    x = GlobalFree(hMem)
    
    ' Verify that t() = s(), which it should
    For c = 0 To 255
    If s(c) <> t(c) Then Debug.Print "Copy attempt failed."
    End If
    I changed it to, and it works
    Code:
    Private Sub Form_Click()
    Dim s(0 To 2) As Long, t(0 To 2) As Long ' arrays to copy from/to
    Dim c As Integer, retval As Long ' counter variable & return value
    Dim hMem As Long, pMem As Long ' handle and pointer to memory block
    Dim x As Long
    ' Initialize the source array s()'s data
    s(0) = 1
    s(1) = 2
    s(2) = 3
    ' Allocate a moveable block of memory (returns a handle) (Integer type = 2 bytes, Long type = 8 bytes)
    hMem = GlobalAlloc(GMEM_MOVEABLE Or GMEM_ZEROINIT, 256 * 8)
    ' Lock the memory block, returning a pointer to it
    pMem = GlobalLock(hMem)
    ' Copy the entire contents of s() to the memory block
    ' Note that pMem is ByVal because we want its contents, not a pointer to it
    CopyMemory ByVal pMem, s(0), 3 * 8
    ' Copy the contents of the memory block to t() (we could have just copied s() to t())
    CopyMemory t(0), ByVal pMem, 3 * 8
    ' Unlock the memory block, destroying the pointer and freeing resources
    x = GlobalUnlock(hMem)
    ' Free the memory block (de-allocate it)
    x = GlobalFree(hMem)
    
    ' Verify that t() = s(), which it should
    For c = 0 To 2
    If s(c) <> t(c) Then
    Debug.Print "Copy attempt failed."
    Else
    Debug.Print t(c)
    End If
    Next
    End Sub
    Ok so since long type is 8 I thought it would be 256 * 8 bytes for space required, but the 3 * 8 not sure if this is right, I think it means #of array * 8 bytes (long type)

  11. #11

    Thread Starter
    PowerPoster
    Join Date
    Aug 2011
    Location
    B.C., Canada
    Posts
    2,887

    Re: Need Full Understanding of VarPtr, StrPtr, ObjPtr

    Thanks Bonnie it cleared up some confusion I had!

    Code:
    Private Declare Function SysReAllocString Lib "oleaut32.dll" (ByVal pBSTR As Long, Optional ByVal pszStrPtr As Long) As Long
    
    
    Public Function GetStrFromPtr(ByVal Ptr As Long) As String
        SysReAllocString VarPtr(GetStrFromPtr), Ptr
    End Function
    
    Private Sub Command1_Click()
    Dim str1 As String
    Dim RetVal As Long
    
    str1 = "Testing"
    RetVal = StrPtr(str1)
    Debug.Print RetVal
    Debug.Print GetStrFromPtr(RetVal)
    End Sub

  12. #12
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,060

    Re: Need Full Understanding of VarPtr, StrPtr, ObjPtr

    Quote Originally Posted by Max187Boucher View Post
    Ok so since long type is 8 ...
    The Long data type actually occupies just 4 Bytes, not 8.

    Quote Originally Posted by Max187Boucher View Post
    ... I thought it would be 256 * 8 bytes for space required, but the 3 * 8 not sure if this is right, I think it means #of array * 8 bytes (long type)
    The amount of memory required for the array elements is calculated as:

    Code:
    Number of Elements * Size of an Element
    Therefore, you need to allocate 3 * 4 = 12 Bytes of memory for your Long array.
    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

  13. #13

    Thread Starter
    PowerPoster
    Join Date
    Aug 2011
    Location
    B.C., Canada
    Posts
    2,887

    Re: Need Full Understanding of VarPtr, StrPtr, ObjPtr

    I was just looking at the table here

    http://msdn.microsoft.com/en-us/library/47zceaw7.aspx

    it said long was 8 bytes haha but maybe its a different long type?

  14. #14
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,060

    Re: Need Full Understanding of VarPtr, StrPtr, ObjPtr

    Quote Originally Posted by Max187Boucher View Post
    it said long was 8 bytes haha but maybe its a different long type?
    That table is for VB.NET! Here's the Data Type Summary table for VB6.
    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

  15. #15

    Thread Starter
    PowerPoster
    Join Date
    Aug 2011
    Location
    B.C., Canada
    Posts
    2,887

    Re: Need Full Understanding of VarPtr, StrPtr, ObjPtr

    About post #10 is it possible to store a string array with those api or is it only for number array?

    Is CopyMemory a lot faster then just using

    Code:
    t = s
    Code:
    '...............Code.....................
    CopyMemory ByVal pMem, s(0), 3 * 8
    CopyMemory t(0), ByVal pMem, 3 * 8
    '...............Code.....................
    Last edited by Max187Boucher; Mar 29th, 2014 at 09:24 PM.

  16. #16
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,060

    Re: Need Full Understanding of VarPtr, StrPtr, ObjPtr

    Quote Originally Posted by Max187Boucher View Post
    About post #10 is it possible to store a string array with those api or is it only for number array?
    Dynamic String arrays are trickier because dynamic Strings are actually composed of a pointer (the String variable itself) and the separately stored string data. If you were to substitute String arrays for your Long arrays in post #10, you would be duplicating the pointers, but not the data. I'm not entirely sure of this, but I believe you'll get a crash when VB tries to deallocate the string data for the second time.

    Quote Originally Posted by Max187Boucher View Post
    Is CopyMemory a lot faster then just using ...
    I don't know. I haven't done any tests regarding that. I have a hunch, however, that the simple array assignment would be a bit faster than CopyMemory.
    Last edited by Bonnie West; Mar 29th, 2014 at 10:50 PM.
    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

  17. #17
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,253

    Re: Need Full Understanding of VarPtr, StrPtr, ObjPtr

    Quote Originally Posted by Max187Boucher View Post

    Is CopyMemory a lot faster then just using

    Code:
    t = s
    No, the above will work faster, because the VB-runtime (when it does calls into the C-runtime,
    as e.g. memcpy) can use a more direct way, without wrapping lib-calls in extra Error-Handlers,
    as is the case with defines which used VBs Declare-Statements (one can speed such calls up
    though, when those flat-API-Declarations were done in a TypeLibrary with the right flags).

    Quote Originally Posted by Max187Boucher View Post
    About post #10 is it possible to store a string array with those api or is it only for number array?
    As Bonnie already said, this is trickier, because Strings, Arrays and Objects are all
    Types which contain additional Pointers in their 4Byte long "Value-Slot".

    You can understand that better, if you look at an UDT (instead of an Array-allocation,
    which is basically the same thing - but we can write up an UDT and the block of
    memory it occupies after allocation more "visually speaking":

    E.g. an UDT which contains 5 Longs:

    Code:
    Type t5Longs
      L0 As Long
      L1 As Long
      L2 As Long
      L3 As Long
      L4 As Long
    End Type
    
    Dim LLLLL As t5Longs
    The variable above will occupy 5*(4Bytes per Long)=20Bytes of Memory.
    The data-area of a VB-SafeArray of Type Long L(0 to 4) as Long will be allocated with the same amount of Bytes.

    The "5 slots" of the above UDT will contain direct Value-Content (the 32Bit Long-Value itself).

    Copying the whole block (as well as deleting or overwriting with Zeros) is entirely unproblematic,
    since the Members (the slots) contain only "true-in-place-values".

    Now a String-based UDT (a VB-String-arrays data-area is again very comparable):

    Code:
    Type t5Strings
      S0 As String
      S1 As String
      S2 As String
      S3 As String
      S4 As String
    End Type
    
    Dim SSSSS As t5Strings
    Here the same amount of Memory as in the Long-UDT above is occupied and allocated,
    for the UDT (the struct) istself. The initial String-Members will contain Zero-Values.

    The same allocation of only 5*(4Bytes per Pointer)=20Bytes is true BTW also for the above
    mentioned Object-Types and VBs dynamic Array-Types.

    But let's stick for the explanation with our String-Types, which occupy these 5
    "Pointer-Slots".

    A Pointer is a Variable or (as in our String-UDT-case) "a Slot-member" which contains
    a 32Bit-LongValue, which expresses "another allocated memory-location where I can
    find more concrete stuff". So, a Pointer-Type expresses "an indirection" - its 4 Byte-
    Value contains and desribes only a 32Bit Address - under which "more stuff" is placed.

    As Long as our String-UDT above contains still "truly empty vbNullStrings" (as is the case
    shortly after initializing with all VB-allocated Variables, UDTs and Arrays), the amount of
    Memory which is snapped away from the process's available Memory is still the same as
    with the 't5Longs'-struct which contains our pure Long-Members (20Byte).

    But other than these True-Value-Typed Long-UDT, our String-UDT will cause more
    "mem-consumption" when we fill real String-Content into its members.

    E.g. when you do:
    SSSSS.S0 = "ABC"
    ... then an additional allocation takes place for the 3 Chars in our (V)BString
    (exactly 4Bytes = 32Bit for the leading Len-Descriptor of our BSTR, followed by
    3*2Bytes for the 3 16Bit-WChars + one trailing Zero-WChar - so the extra-
    amount of memory which is caused by the assignment above is 4+6+2=12Bytes.

    I think it's obvious that these 12Bytes do not fit into the 4Byte-length of our
    t5Strings.S0 slot, so only the Address of this new allocated Mem-Area is stored there.

    That's why I help myself often with the term "sidewards allocated (extra-)memory"
    (when you consider how you type an UDT and its Members in a "Top-Down-fashion").

    And since it is such extra-allocated memory which is contained in VBs pointer-types
    (Strings, Objects, DynArrays), it is a bit more difficult to "simply copy them".

    As said, a LenB(SSSSS) would give 20Bytes in the same way as LenB(LLLLL) would
    give 20Bytes.

    But when you copy the content of SSSSS into another (yet empty) target-area,
    as for example defined per Dim SSSSS2 As t5Strings, then you will have only
    two sets of the same 5 pointers (in case you do it "by hand" per CopyMemory,
    and thus "undetected by the VB-compiler, to take measures").

    In case of Pointer-Types the VB-Compiler does "hard work" under the hood, to keep
    track to perform correct copying (automatically doing the needed sidewards-allocations
    on the target) and also when freeing such an UDT (or an array) which contains pointer-
    Types.
    In case of our CopyMemory-action into SSSSS2 (which then contains the very same
    set of String-Pointers, pointing to the same allocated String-Areas) only the first
    UDT which gets deleted, will behave without any issues. The Pointer-Slots which
    remain filled in the second UDT will point to "dead memory" (nothing there anymore,
    the memory was deallocated whilst the first UDT was cleared by the compiler).

    That's prone to cause exceptions due to so called "double freeing", when you not
    take care about, that you reset the String-Member slots to Zero "by hand"
    (the VB-Runtime* will not free Pointer-Members which are Zero - a NullPointer
    represents an "unallocated state")

    *edit, to correct the formerly used: 'VB-Compiler'

    Ok, enough for the moment I think.

    Olaf
    Last edited by Schmidt; Mar 30th, 2014 at 03:27 AM.

  18. #18

    Thread Starter
    PowerPoster
    Join Date
    Aug 2011
    Location
    B.C., Canada
    Posts
    2,887

    Re: Need Full Understanding of VarPtr, StrPtr, ObjPtr

    Thanks Bonnie and Schmidt, I finally understand the basic of it now, will have to play with this a bit more to get familiar with it. I will mark as resolved and I'll post more questions when i get stuck somewhere.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width