Page 2 of 2 FirstFirst 12
Results 41 to 68 of 68

Thread: Len vs LenB for specifying API structure lengths, and internal vs end padding

  1. #41
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    7,600

    Re: Len vs LenB for specifying API structure lengths, and internal vs end padding

    Quote Originally Posted by wqweto View Post
    One reason no one noticed how evil Len actually is stems from such careful UDT declarations in API Viewer, so that both Len and LenB lead to the same "[url=https://blog.codinghorror.com/falling-into-the-pit-of-success/]pit of
    Yes, exactly! This is precisely the reason it's is so difficult to get people to understand that they shouldn't be using Len to measure a UDT's true size in memory. For example:-
    Code:
    Private Type n1
        a As Long
        b As Long
    End Type
    Len would measure the above structure correctly because the structure is naturally aligned and contains no Strings. Since the most common structures are naturally aligned and don't contain Strings, it gives people a false sense of security. Most people don't even realize that the reason Len works is because they got lucky. If you change the above structure even slightly, say like this:-
    Code:
    Private Type n1
        a As Long
        b As Long
        c As Byte
    End Type
    Now the compiler has to add 3 padding bytes to that so the next address falls on a 4 byte boundary. Len would not report that but LenB will.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  2. #42
    Addicted Member
    Join Date
    Oct 2011
    Posts
    179

    Re: Len vs LenB for specifying API structure lengths, and internal vs end padding

    Quote Originally Posted by Niya View Post
    YES!



    Use LenB to measure structures and Len to measure strings by character count. Never use Len to measure a structure unless it's about saving a structure to or loading from a file as trick pointed out. If files aren't involved, use LenB.
    With ANSI and ByRef strings LenB does not work. Period.

  3. #43
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    7,600

    Re: Len vs LenB for specifying API structure lengths, and internal vs end padding

    Quote Originally Posted by argen View Post
    No so fast.

    If you need to handle ANSI APIs ByRef, and you are declaring strings in the UDT (like it was common practice in old code, in the old times), you need to use Len and not LenB.
    But take care of something: use even character counts, not uneven.
    This is a trap. You should be using LenB not Len. Take the following:-
    Code:
    Private Type DATA
        a As String * 4
        b As Long
    End Type
    Len reports that UDT as 8 bytes long. The thing is, it is not 8 bytes long, it's actual 12 bytes long in memory. Now if you pass it to ByRef to an external function, the ANSI to Unicode conversion would create a structure like this behind the scenes:-
    Code:
    Private Type ANSIDATA
        a(1 To 4) As Byte 'Converted from Unicode to ANSI
        b As Long
    End Type
    The above structure is 8 bytes long so Len got it right. Many people would walk away thinking they did the right thing but they don't realize that it works because the structure is naturally aligned after it's been converted to ANSI. All you have to do to break this is change the length of the string like this:-
    Code:
    Private Type DATA
        a As String * 2
        b As Long
    End Type
    Len would measure that at 6 bytes. However, if you converted that to ANSI, it would be 8 bytes, not 6 . Len didn't count the padding added to align the converted structure.

    There are a few tricks you could use to get it to work but the best way is to avoid the Unicode to ANSI conversion by declaring the String as a byte array and using LenB for all measuring. You will always get the correct behavior whether your UTD is naturally aligned or not.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  4. #44
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    7,600

    Re: Len vs LenB for specifying API structure lengths, and internal vs end padding

    Here is proof that using Len is wrong:-
    Code:
    Private Declare Sub MemCpy Lib "Kernel32.dll" Alias "RtlMoveMemory" (ByRef dest As Any, ByRef src As Any, ByVal cb As Long)
    
    Private Type MYUDT
        strVal As String * 6
        lngVal As Long
    End Type
    
    Private Type MYUDT2
        strVal(1 To 6) As Byte
        lngVal As Long
    End Type
    
    Private Sub Form_Load()
        Dim b() As Byte
        
        b = StrConv("ABCDEF", vbFromUnicode)
        
        Dim data1 As MYUDT
        Dim data2 As MYUDT2
        
        Dim copy1 As MYUDT
        Dim copy2 As MYUDT2
        
        data1.lngVal = &HFF0000FF
        data1.strVal = "ABCDEF"
        
        data2.lngVal = &HFF0000FF
        AssignANSI data2.strVal, "ABCDEF"
        
        'This is the wrong way to do it because
        'Len doesnt account for padding after the UDT
        'has been converted to ANSI
        MemCpy copy1, data1, Len(data2)
        
        'This is the correct way to do it. We use a UDT
        'with a byte array instead of a String to bypass VB6's Unicode to ANSI
        'conversion and we use LenB to measure the structure
        MemCpy copy2, data2, LenB(data2)
        
        Debug.Print "-----------------------"
        Debug.Print "Orginal values in String UDT"
        Debug.Print "-----------------------"
            
        PrintData data1
        
        Debug.Print "-----------------------"
        Debug.Print "Orginal values in byte array UDT"
        Debug.Print "-----------------------"
            
        PrintData2 data2
        
        
        Debug.Print "-----------------------"
        Debug.Print "String UDT copied using Len"
        Debug.Print "-----------------------"
        
        PrintData copy1
    
    
        Debug.Print "-----------------------"
        Debug.Print "Byte array UDT copied using LenB"
        Debug.Print "-----------------------"
        
        PrintData2 copy2
    
    
    
    
    End Sub
    
    Private Sub AssignANSI(ar() As Byte, s As String)
        
        Dim b() As Byte
        Dim x As Long
        
        x = LBound(ar)
        
        b = StrConv(s, vbFromUnicode)
        
        For i = LBound(b) To UBound(b)
            ar(x) = b(i)
            x = x + 1
        Next
        
        
    
    End Sub
    
    Private Sub PrintData(data As MYUDT)
        
        Debug.Print "lngVal = " & Hex(data.lngVal)
        Debug.Print "strVal = " & data.strVal
        
    End Sub
    
    Private Sub PrintData2(data As MYUDT2)
        
        Debug.Print "lngVal = " & Hex(data.lngVal)
        Debug.Print "strVal = " & StrConv(data.strVal, vbUnicode)
        
    End Sub
    The above outputs this:-
    Code:
    -----------------------
    Orginal values in String UDT
    -----------------------
    lngVal = FF0000FF
    strVal = ABCDEF
    -----------------------
    Orginal values in byte array UDT
    -----------------------
    lngVal = FF0000FF
    strVal = ABCDEF
    -----------------------
    String UDT copied using Len
    -----------------------
    lngVal = FF
    strVal = ABCDEF
    -----------------------
    Byte array UDT copied using LenB
    -----------------------
    lngVal = FF0000FF
    strVal = ABCDEF
    When the original data was copied using Len to measure it, the data was corrupted. Highlighted in red is the corruption. The value of the lngVal when copied should be FF0000FF but instead it's FF.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  5. #45
    Addicted Member
    Join Date
    Oct 2011
    Posts
    179

    Re: Len vs LenB for specifying API structure lengths, and internal vs end padding

    Niya, I thought you already had understood all this.

  6. #46
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    7,600

    Re: Len vs LenB for specifying API structure lengths, and internal vs end padding

    Prove me wrong then. Show me how to copy this structure correctly using Len and passing by reference through an external API like RTLMoveMemory.
    Code:
    Private Type MYUDT
        strVal As String * 6
        lngVal As Long
    End Type
    Do that and I will concede.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  7. #47
    Addicted Member
    Join Date
    Oct 2011
    Posts
    179

    Re: Len vs LenB for specifying API structure lengths, and internal vs end padding

    LOL! You need to add one more byte per string for the last null of the BSTR.
    This is really weird.

  8. #48
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    7,600

    Re: Len vs LenB for specifying API structure lengths, and internal vs end padding

    Quote Originally Posted by argen View Post
    LOL! You need to add one more byte per string for the last null of the BSTR.
    This is really weird.
    What do you mean?
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  9. #49

    Thread Starter
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    7,820

    Re: Len vs LenB for specifying API structure lengths, and internal vs end padding

    Quote Originally Posted by argen View Post
    LOL! You need to add one more byte per string for the last null of the BSTR.
    This is really weird.
    It's two bytes (Unicode). It's so we can use StrPtr and then have a library treat it like a StrZ string.

    And FYI, fixed-length strings don't do this.
    Last edited by Elroy; Jun 23rd, 2022 at 04:33 PM.
    Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.

  10. #50
    Addicted Member
    Join Date
    Oct 2011
    Posts
    179

    Re: Len vs LenB for specifying API structure lengths, and internal vs end padding

    Quote Originally Posted by Niya View Post
    What do you mean?
    No, I really don't know anymore what it is doing. I put 6 characters and then count 7 + 1 null char.

    Code:
        Option Explicit
        
        Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)
        
        Private Type MYUDT
            strVal As String * 6
            lngVal As Long
        End Type
        
        Private Sub Form_Load()
            Dim x As MYUDT
            Dim ba1() As Byte
            Dim c As Long
            
            x.strVal = String$(6, "A")
            x.lngVal = &H7FFFFFFF
            
            ReDim ba1(LenB(x) - 1)
            CopyMemory ByVal VarPtr(ba1(0)), x, LenB(x)
            
            For c = 0 To LenB(x) - 1
                Debug.Print c, ba1(c)
            Next
            Debug.Print
        End Sub

  11. #51
    Addicted Member
    Join Date
    Oct 2011
    Posts
    179

    Re: Len vs LenB for specifying API structure lengths, and internal vs end padding

    Code:
    Option Explicit
    
    Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)
    
    Private Type MYUDT
        strVal As String * 6
        lngVal As Long
    End Type
    
    Private Sub Form_Load()
        Dim x As MYUDT
        Dim ba1() As Byte
        Dim c As Long
        
        x.strVal = "ABCAEF" ' <---- whatever you put there in place of the "A", you get that also at the end (plus a null char).
        x.lngVal = &H7FFFFFFF
        
        ReDim ba1(LenB(x) - 1)
        CopyMemory ByVal VarPtr(ba1(0)), x, LenB(x)
        
        For c = 0 To LenB(x) - 1
            Debug.Print c, ba1(c)
        Next
        Debug.Print
    End Sub
    Code:
     0             65 
     1             66 
     2             67 
     3             65 
     4             69 
     5             70 
     6             65 
     7             0 
     8             255 
     9             255 
     10            255 
     11            127 
     12            128 
     13            42 
     14            178 
     15            6

  12. #52
    Addicted Member
    Join Date
    Oct 2011
    Posts
    179

    Re: Len vs LenB for specifying API structure lengths, and internal vs end padding

    OK, it must be that also ANSI must be padded to 4 bytes batchs, they are also Win32 after all.
    I'll delete the posts where I said that the number of characters needed to be even, that does not seems correct now.

  13. #53

    Thread Starter
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    7,820

    Re: Len vs LenB for specifying API structure lengths, and internal vs end padding

    Ok, you've made precisely the mistake that's been repeatedly mentioned above:

    Code:
    
    Option Explicit
    
    Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)
    
    Private Type MYUDT
        strVal As String * 6
        lngVal As Long
    End Type
    
    Private Sub Form_Load()
        Dim x As MYUDT
        Dim ba1() As Byte
        Dim c As Long
    
        x.strVal = "ABCAEF" ' <---- whatever you put there in place of the "A", you get that also at the end (plus a null char).
        x.lngVal = &H7FFFFFFF
    
        ReDim ba1(LenB(x) - 1)
        CopyMemory ByVal VarPtr(ba1(0)), ByVal VarPtr(x), LenB(x)
    
        For c = 0 To LenB(x) - 1
            Debug.Print c, ba1(c)
        Next
        Debug.Print
    End Sub
    
    
    Output, precisely as it should be:
    Code:
     0            65 
     1            0 
     2            66 
     3            0 
     4            67 
     5            0 
     6            65 
     7            0 
     8            69 
     9            0 
     10           70 
     11           0 
     12           255 
     13           255 
     14           255 
     15           127
    Making API calls often screws with our input unless we know what we're doing.
    Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.

  14. #54
    Addicted Member
    Join Date
    Oct 2011
    Posts
    179

    Re: Len vs LenB for specifying API structure lengths, and internal vs end padding

    Elroy, you are not following what I was testing. I did that on purpose, for testing the conversion to ANSI that VB6 performs behind curtains.

    (where Len could be used... allegedly)

  15. #55
    Addicted Member
    Join Date
    Oct 2011
    Posts
    179

    Re: Len vs LenB for specifying API structure lengths, and internal vs end padding

    And that's not "a mistake". It is a way of working. It used to be the more or less norm 20 years ago (when ANSI was common).

  16. #56

    Thread Starter
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    7,820

    Re: Len vs LenB for specifying API structure lengths, and internal vs end padding

    Also, this is another very good example of why we should "default" to LenB and not Len. Len would have made that example much more difficult.
    Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.

  17. #57
    Addicted Member
    Join Date
    Oct 2011
    Posts
    179

    Re: Len vs LenB for specifying API structure lengths, and internal vs end padding

    Quote Originally Posted by Elroy View Post
    Also, this is another very good example of why we should "default" to LenB and not Len. Len would have made that example much more difficult.
    There are cases where not Len nor LenB can give you the exact size.

    In this particular case Len returns less, and LenB returns more.
    I preferred more for my test, but it does not imply that it would be right for production code.

  18. #58

    Thread Starter
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    7,820

    Re: Len vs LenB for specifying API structure lengths, and internal vs end padding

    And, I guess another point we're beating to death is that a 2-byte Unicode null-terminator, when converted to ANSI (maybe with StrConv, or what API calls do), becomes a 1-byte null-terminator. I'm not sure there's anything new there though.

    EDIT: Less? More? How about just "accurate", for whatever the intended purpose is.
    Last edited by Elroy; Jun 23rd, 2022 at 05:30 PM.
    Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.

  19. #59
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    7,600

    Re: Len vs LenB for specifying API structure lengths, and internal vs end padding

    Quote Originally Posted by argen View Post
    Elroy, you are not following what I was testing. I did that on purpose, for testing the conversion to ANSI that VB6 performs behind curtains.

    (where Len could be used... allegedly)
    I see that you've used LenB in your code. Why did you do that after insisting that Len was the only way? I wanted to see you copy the entire UDT after measuring it with Len because you claimed Len is the right way to do it.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  20. #60
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    7,600

    Re: Len vs LenB for specifying API structure lengths, and internal vs end padding

    Quote Originally Posted by argen View Post
    There are cases where not Len nor LenB can give you the exact size.
    LenB always tells you the exact size of a structure in memory. The reason you think it doesn't sometimes is because you're expecting it to correctly measure the structure after it's been passed to an API by reference and the String members are converted to ANSI. LenB can't know in advance that you're going to convert it to an ANSI structure. This is why I keep saying to avoid doing Unicode to ANSI conversions that way.

    You think Len is the right way because Len measures the character count of a string which by pure chance happens to be synonymous with the byte length of an ANSI String. But the problem here is that Len doesn't count padding so the minute you pass a structure that isn't naturally aligned, Len would give you an incorrect measurement.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  21. #61
    Addicted Member
    Join Date
    Oct 2011
    Posts
    179

    Re: Len vs LenB for specifying API structure lengths, and internal vs end padding

    Quote Originally Posted by Elroy View Post
    EDIT: Less? More? How about just "accurate", for whatever the intended purpose is.
    There is not accurate function for those cases.

  22. #62
    Addicted Member
    Join Date
    Oct 2011
    Posts
    179

    Re: Len vs LenB for specifying API structure lengths, and internal vs end padding

    I can't read your longs posts Niya.

    I used Len because I didn't want to get the size of the UDT in memory, but the size of the UDT that VB6 passes to the API.
    It turned to be more complex after all.

    In conclusion, do not use Len or LenB blindly.

    The rules are:

    For LenB:
    Declare all as byte arrays, or integer arrays or long arrays (or not arrays, whatever).
    But if you use other than longs, pad them in 4 bytes packs.
    You can declare String * N if you want, but then just use the API declaration ByVal As Long (and not ByRef As Any). Also pad in 4 bytes (even number of characters).

    If you didn't use any String * N type, you can declare the API ByRef or ByVal. If you do ByVal, the type should be Long and call it using VarPtr.
    If you declare ByRef the type as Any and send it by reference (no VarPtr).

    Rules for Len:
    Useful when there are strings.
    The number of characters of the strings must be a multiple of 4 (I hope I'm right now regarding this).
    In the same way pad all the bytes(1), integer(2) and boolean(2) in packs of 4 bytes.

    Call the ANSI API version ByRef (As Any).

    So, always the "rule" is to make the right padding. But I guess APIs are already declared in that way, so we don't need to worry.

    Bottom line: LenB cannot be used in the last case.
    Len cannot be used in the first case either.

    Yes, I was not totally right in what I said at first, but you weren't either.

    PS: I wonder how can this declaration behave:

    Code:
    Private Type MYUDT
        strVal As String * 6
        lngVal As Long
    End Type
    
    Private Declare Sub CopyMemory Lib "kernel32.dll" Alias _
         "RtlMoveMemory" (ByRef Destination As Any, ByVal Source As MYUDT, ByVal Length As Long)
    I'll test that later.
    Last edited by argen; Jun 23rd, 2022 at 06:27 PM.

  23. #63
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    7,600

    Re: Len vs LenB for specifying API structure lengths, and internal vs end padding

    Quote Originally Posted by argen View Post
    In conclusion, do not use Len or LenB blindly.

    The rules are:

    For LenB:
    Declare all as byte arrays, or integer arrays or long arrays (or not arrays, whatever).
    But if you use other than longs, pad them in 4 bytes packs.
    You can declare String * N if you want, but then just use the API declaration ByVal As Long (and not ByRef As Any). Also pad in 4 bytes (even number of characters).

    If you didn't use any String * N type, you can declare the API ByRef or ByVal. If you do ByVal, the type should be Long and call it using VarPtr.
    If you declare ByRef the type as Any and send it by reference (no VarPtr).

    Rules for Len:
    Useful when there are strings.
    The number of characters of the strings must be a multiple of 4 (I hope I'm right now regarding this).
    In the same way pad all the bytes(1), integer(2) and boolean(2) in packs of 4 bytes.

    Call the ANSI API version ByRef (As Any).

    So, always the "rule" is to make the right padding. But I guess APIs are already declared in that way, so we don't need to worry.

    Bottom line: LenB cannot be used in the last case.
    Len cannot be used in the first case either.
    This is overly complicated and very error prone. Here's a much simpler set of rules.

    • Use LenB only. Never use Len
    • For Unicode structures, fixed length Strings should be declared as String * Length and the structure passed using VarPtr.
    • For ANSI structures, fixed length strings should be declared as Byte(0 to Length-1) and the structure passed by reference or using VarPtr.


    That's it. That is all you need it your code will always work. No need for messy details like checking for multiples of 4 or padding the structures yourself.

    Quote Originally Posted by argen View Post
    Yes, I was not totally right in what I said at first, but you weren't either.
    Your assertion was that Len is right way to go about measuring an ANSI structure. I countered by suggesting that it will fail under certain conditions. I then showed you a situation where it fails to measure a structure properly. So I was not wrong. I also showed multiple times the correct way to measure an ANSI structure.

    For me to be wrong, you have to show that Len can successfully measure all ANSI structures. It must work all the time and not only on certain structures.

    Quote Originally Posted by argen View Post
    PS: I wonder how can this declaration behave:

    Code:
    Private Type MYUDT
        strVal As String * 6
        lngVal As Long
    End Type
    
    Private Declare Sub CopyMemory Lib "kernel32.dll" Alias _
         "RtlMoveMemory" (ByRef Destination As Any, ByVal Source As MYUDT, ByVal Length As Long)
    I'll test that later.
    That won't compile. You cannot pass UDTs by value in VB6.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  24. #64
    Addicted Member
    Join Date
    Oct 2011
    Posts
    179

    Re: Len vs LenB for specifying API structure lengths, and internal vs end padding

    Yes, you were wrong Niya. You position was that LenB could work on any situation, that it always returned the right length, and that's turned to be not true (unless of course, if you change the declaration in the UDT, and that's not any situation anymore then).

    You also said that Len was not necessary at all. And it turned to be that it is needed for files.

    What's the problem with the people to accept when they are wrong? (I see that that happens to most of the people)

  25. #65
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    7,600

    Re: Len vs LenB for specifying API structure lengths, and internal vs end padding

    Quote Originally Posted by argen View Post
    Yes, you were wrong Niya. You position was that LenB could work on any situation, that it always returned the right length, and that's turned to be not true (unless of course, if you change the declaration in the UDT, and that's not any situation anymore then).
    I said you should never be using Len to measure structures because there are situations where it would not work. I also presented this structure as a test case:-
    Code:
    Private Type MYUDT
        strVal As String * 6
        lngVal As Long
    End Type
    No matter what you do, Len will not measure that correctly. However, if you used LenB, you will get the correct measurement. And if you involve ANSI conversions LenB should still be used with the Strings changed to byte arrays. The only way Len would work here is if you pad the structure yourself like this:-
    Code:
    Private Type MYUDT
        strVal As String * 6
        padding As Integer 
        lngVal As Long
    End Type
    And lets be real here, do we really want to start manually padding our structures just to get Len to work? With a large structure you could end up with bastardized thing filled with a bunch of ghost members. Is Len really worth all this trouble? And to make matters worse that only works if you intend to measure the ANSI version of that structure. What if you wanted to measure it's actually Unicode length? The manual padding will screw up the measurement.

    Quote Originally Posted by argen View Post
    You also said that Len was not necessary at all. And it turned to be that it is needed for files.
    We aren't talking about files. We are talking about memory.

    Quote Originally Posted by argen View Post
    What's the problem with the people to accept when they are wrong? (I see that that happens to most of the people)
    My position is that LenB is always better than using Len to measure structures in memory, not for files, in memory. I've seen nothing in this thread that has convinced me that Len should be ever be preferred to LenB. Using Len to measure structures invites all kinds of mayhem. It should not be used for this.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  26. #66
    Addicted Member
    Join Date
    Oct 2011
    Posts
    179

    Re: Len vs LenB for specifying API structure lengths, and internal vs end padding

    Quote Originally Posted by Niya View Post
    My position is that LenB is always better than using Len to measure structures in memory, not for files, in memory. I've seen nothing in this thread that has convinced me that Len should be ever be preferred to LenB. Using Len to measure structures invites all kinds of mayhem. It should not be used for this.
    Yes.

  27. #67
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Posts
    3,924

    Re: Len vs LenB for specifying API structure lengths, and internal vs end padding

    > And lets be real here, do we really want to start manually padding our structures just to get Len to work?

    Been there done that. Now I realize that this was only to *force* Len to return correct size (even padded last non-Long member).

    > With a large structure you could end up with bastardized thing filled with a bunch of ghost members.

    No, the struct size in memory and the result by LenB actually does not change by the "basterdized" padding introduced to appease Len.

    > Is Len really worth all this trouble?

    If you don't know better I repeat -- been there done that :-))

    cheers,
    </wqw>

  28. #68

Page 2 of 2 FirstFirst 12

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