Results 1 to 26 of 26

Thread: Creating a large string in a private heap

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Mar 2019
    Posts
    515

    Creating a large string in a private heap

    So I have a project that must run on 32bit and 64 bit windows. On 32 bit windows I sometimes get the dreaded "out of string space" error. I have tried as best I can to modify the code to use string buffers etc but it still happens sometimes

    Using the information contained in this post I thought about creating a private heap to keep my large strings in.

    https://www.vbforums.com/showthread....ocess-s-memory

    The rough trial code looks like this. Is this a terrible idea? If it is then what would I need to do to make it workable. If its not what have I left out. I am not checking heap function status but I will. Does anyone know if out of string space means some limit has been hit or just that the default heap is too fragmented for the new allocation when I need to copy a string or pass it back up the stack. ( i guess this makes a new string)

    Code:
     Dim lngPointer As Long
          Dim strString As String
          Dim lngPointer1 As Long
          Dim lngLength As Long
          Dim newLength As Long
          Dim oldBstrPtr As Long
          Dim oldStrPtr As Long
          Dim oldBStrLength As Long
    
    10    newLength = 2048
    
    20    strString = "a"
    
    30    lngPointer = StrPtr(strString)
    
          ' save the old string pointer
    
    40    oldStrPtr = lngPointer
          ' save the pointer to the old bStr
    
    50    CopyMemory oldBstrPtr, ByVal lngPointer, 4
    
          ' save the old length
    
    60    CopyMemory oldBStrLength, ByVal lngPointer - 4, 4
          '
          ' The 4 bytes immediately before the BSTR is the length of the string
          '
          ' Create a heap
    
    70    hHeap = HeapCreate(0, 1024& * 1024, 0)
    
          ' allocate some memory
    
    80    ptrHBlock = HeapAlloc(hHeap, 0, 2048)
    
          ' copy the address of the memory we allocated to to the old bstr address
    
    90    CopyMemory ByVal lngPointer, ptrHBlock, 4
    
          ' copy the new length we want
          
    100   CopyMemory ByVal lngPointer - 4, newLength, 4
        
    ' in theory I now have a string in a private heap
    
    ' Put it all back the way it was
    
    110   CopyMemory ByVal lngPointer, oldBstrPtr, 4
    
    120   CopyMemory ByVal lngPointer - 4, oldBStrLength, 4
    
    'clean up
    130 HeapFree hHeap, 0, ptrHBlock
    
    140 HeapDestroy hHeap

  2. #2
    PowerPoster Arnoutdv's Avatar
    Join Date
    Oct 2013
    Posts
    6,733

    Re: Creating a large string in a private heap

    How big is big?
    Often the problem arises when you are on the edge of your memory buffer and new space needs to be allocated.
    Then at least twice the memory is needed, the original buffer and the new increased buffer.

  3. #3

    Thread Starter
    Fanatic Member
    Join Date
    Mar 2019
    Posts
    515

    Re: Creating a large string in a private heap

    The project allocates and deallocates lots of small strings so I think things get pretty fragmented. Its linked largeAddressAware on 32 and 64 bit. The problem does not seem to happen on 32 bit

    I this case I need some decompression buffers of about 20 megabytes big. Only 3 at the moment. If for any reason I need to grow them (and I might) the thing gets an out of string space error even though memory utilization is around 1.3 gig. Close to the wind on 32 bits I know.

    But is this s terrible idea?

  4. #4

    Thread Starter
    Fanatic Member
    Join Date
    Mar 2019
    Posts
    515

    Re: Creating a large string in a private heap

    Interestingly I allocate 40 megs of memory, set the length to 40 million. Len(strString) returns 20meg, lenb(strString) returns 40 meg. So far so good.

    But if I try to touch any memory after the first 2 bytes (1 unicode char) which was the size of the thing orionally it crashes

    EDIT - Forgot the terminator 2 bytes
    Last edited by vbwins; Oct 10th, 2024 at 09:29 AM.

  5. #5
    PowerPoster Arnoutdv's Avatar
    Join Date
    Oct 2013
    Posts
    6,733

    Re: Creating a large string in a private heap

    I'm using plain VB6 code to deal with large string (a StringBuilder class)
    No fancy memory APIs and pointer managed.
    I also deal with huge strings sometimes (text files in memory).
    The critical point is when increasing the StringBuilder buffer, then you need twice the memory.

    A string can have a maximum size of 2GB.
    How do you allocate new memory space when exceeding the for example the 1GB buffer?
    Do you double the capacity or increase it in smaller steps?

  6. #6

    Thread Starter
    Fanatic Member
    Join Date
    Mar 2019
    Posts
    515

    Re: Creating a large string in a private heap

    So it been running for a few hours and just stopped in Windbg trying to allocate a plain old dynamic string

    unCompressedString = Space$(containedUncompressedLen + 256000)

    where containedUncompressedLen = 22884489

    It got passed a compressed (zlib) string of length 1340757. The compressed string has the previously uncompressed length in the header in plain text. 22884489.

    All it was trying to do is make space for the decompression.

    For what its worth Task Manager committed memory is about 1.4 gig for the process.

  7. #7
    PowerPoster Arnoutdv's Avatar
    Join Date
    Oct 2013
    Posts
    6,733

    Re: Creating a large string in a private heap

    If containedUncompressedLen = 22.884.489 then the string space allocated is: 2 * (containedUncompressedLen + 256.000)
    But why are you using Strings instead of byte arrays?

  8. #8

    Thread Starter
    Fanatic Member
    Join Date
    Mar 2019
    Posts
    515

    Re: Creating a large string in a private heap

    Quote Originally Posted by Arnoutdv View Post
    If containedUncompressedLen = 22.884.489 then the string space allocated is: 2 * (containedUncompressedLen + 256.000)
    But why are you using Strings instead of byte arrays?
    It's unicode data just comes from another app over a network and it needs to be parsed in memory. A byte array being returned is possible but sooner or later it needs to be a string.

    I am hoping someone will chime in on the heap thing. Been playing with it today with partial success

  9. #9
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    7,653

    Re: Creating a large string in a private heap

    Perhaps you should look into using higher memory ranges since most systems have more than 2 or 4GB these days, using AWE. Another advantage of this method is you can use it to guarantee the memory isn't paged out to disk.

  10. #10
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    10,909

    Re: Creating a large string in a private heap

    If it's got to run on Windows 32-bit (as well as Windows WoW 64-bit), then stuffing the strings into any "far memory" isn't going to help any. And neither is LAA compiling/linking.

    All the memory a 32-bit Windows machine will address is 4GB, so let's assume you've got one of these 32-bit Windows machine packed with memory. The Windows OS is going to take a sizeable chunk, and then all your "in-memory" services and start-up apps are going to take another sizable chunk. In total, that's probably, in some cases, going to approach 2GB. So, all that's left for VB6 is the remaining 2GB, which can be addressed with no concern about LAA linking.

    Also, that entire 2GB is available to VB6 without any concerns of far memory, or private heap, or anything else. So, if you're getting out of memory (or out of string space) errors, about the only alternative is to start writing things to disk, and then reading pieces as you need them. That's sort of why we have disks in the first place.



    In my primary application, I never had out of memory/string errors, but I was concerned about it. So, for all the 100s (if not 1000s) of places where I might show a MsgBox, I wrote a function that fetches the caption string from an MDB file. All these strings are just cross-referenced with a number (a Long). Because it's a MsgBox (which are basically never processor speed sensitive), there's no slowdown in my program whatsoever.

    If you want me to, I'll post the little function that fetches these strings from the MDB file. Here's the gist of it, but I can post a more detailed explanation of it:

    Code:
    
    Public Function DbTxt(ID As Long, ParamArray sArgs() As Variant) As String
        ' If sArgs are passed, make SURE they're all strings.
        '
        Dim i As Long
        '
        rsStrings.Seek "=", ID
        If rsStrings.NoMatch Then
            If InIDE Then
                MsgBox "IDE Development Error!!!  The Strings.mdb message " & Format$(ID) & " wasn't found."
            End If
            Exit Function
        End If
        DbTxt = rsStrings![English]
        '
        ' And now see if we've got any replacements to make.
        For i = LBound(sArgs) To UBound(sArgs)
            DbTxt = Replace$(DbTxt, "%%", sArgs(i), 1&, 1&, vbBinaryCompare)
        Next
        '
        ' The following is necessary because MS-Access strips trailing spaces and vbCrLf from any Text/Memo fields.
        ' It's a bit unusual, but it does happen, particularly trailing vbCrLf occurrences.
        If InStr(DbTxt, "¶") <> 0 Then DbTxt = Replace$(DbTxt, "¶", vbCrLf, 1&, -1&, vbBinaryCompare)
        If InStr(DbTxt, "§") <> 0 Then DbTxt = Replace$(DbTxt, "§", " ", 1&, -1&, vbBinaryCompare)
    End Function
    
    
    Oh, and just to say it, yeah, virtual memory may kick in to give us a bit more than 2GB, but, if we're that close, we truly need to be writing/reading stuff to/from disk.
    Last edited by Elroy; Oct 10th, 2024 at 04:56 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. To all, peace and happiness.

  11. #11
    PowerPoster
    Join Date
    Jan 2020
    Posts
    5,538

    Re: Creating a large string in a private heap

    You can try to use the memory mapping function.
    For example, create 10 processes, each of which creates a memory file object.
    And then write the string into it.

  12. #12

    Thread Starter
    Fanatic Member
    Join Date
    Mar 2019
    Posts
    515

    Re: Creating a large string in a private heap

    LAA is useful on 64 bit though which is why I use it.

    I want to avoid disk if possible for performance reasons.

    Does anybody know what "out of string space" actually means? Is it a simple heap allocation failure? Is it because of heap fragmentation? Is there some special area of memory VB reserves for string?

    What is the difference between "out of string space" and "out of memory"?

    If I can understand this it may give me a clue as to something else I can change.

    Thanks for the suggestions I will consider them all.

  13. #13

    Thread Starter
    Fanatic Member
    Join Date
    Mar 2019
    Posts
    515

    Re: Creating a large string in a private heap

    Does anybody have an idea on the origional question. Perhaps The Trick?

  14. #14
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    10,909

    Re: Creating a large string in a private heap

    CSharedMemory-class-for-dynamic-memory-allocation-in-shared-memory

    MMapper-Memory-Mapped-File-Demo

    Arrays-in-Far-Memory

    You can use this "far memory" as shared memory across different processes, but it can also just be used by a single process. Again, this is only going to help on 64-bit systems, as it is a way for VB6 to address memory out of the 32-bit 4GB range.

    Also, as a note on LAA, any third-party DLLs and/or OCXs you use, be sure they're all LAA compatible as well. Or, as Dilettante has previously stated, you're setting a time-bomb for yourself. When specifying LAA, you're not "just" specifying it for your source code. You're also specifying it for anything your source code calls as well.
    Last edited by Elroy; Oct 11th, 2024 at 11:24 AM.
    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. To all, peace and happiness.

  15. #15

    Thread Starter
    Fanatic Member
    Join Date
    Mar 2019
    Posts
    515

    Re: Creating a large string in a private heap

    Thanks will take a look. All the code is mine. I tried over negative addresses being returned by some small c++ items years ago but thanks for the heads up.

    I will check out your post above. I think however whioe sleeping I figured out a way to make tye private heap thing work. Will try Monday and report back.

  16. #16

    Thread Starter
    Fanatic Member
    Join Date
    Mar 2019
    Posts
    515

    Re: Creating a large string in a private heap

    Took a look at arrays-in-far memory.

    How do you specify that CreateFileMapping will use memory outside our 32 bit address space? I dont see that in the code.

  17. #17
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    10,909

    Re: Creating a large string in a private heap

    Quote Originally Posted by vbwins View Post
    Took a look at arrays-in-far memory.

    How do you specify that CreateFileMapping will use memory outside our 32 bit address space? I dont see that in the code.
    https://learn.microsoft.com/en-us/wi...tefilemappinga

    All I can do is refer you to Microsoft's reference. And to say, "it just does".

    That's why we get two Long arguments (instead of just one) to address that memory (dwMaximumSizeLow & dwMaximumSizeHigh). It takes two (or a 8 byte LongLong) to address a full 64-bit memory address space.

    Also, the fact that this memory can be shared by two (or more) separate processes is further proof that it's outside the address space of a single VB6 program.

    Vbwins, good luck with your project.
    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. To all, peace and happiness.

  18. #18
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    10,909

    Re: Creating a large string in a private heap

    Also, here's a very similar project developed by Eduardo:

    https://www.vbforums.com/showthread....fit-in-memory)

    His is nice in that he has a variable length string option. And he also broke the task up into several independent CLS files, so you can pick and choose according to your needs.
    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. To all, peace and happiness.

  19. #19
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Creating a large string in a private heap

    Quote Originally Posted by vbwins View Post
    What is the difference between "out of string space" and "out of memory"?
    I'd very much like to know the answer to this as well. Strings are really just binary data interpreted as text so it uses memory just like any other kind of binary data. This error suggests that there is some abstraction in the VB6 runtime that treats strings differently in memory.
    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. #20
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    10,909

    Re: Creating a large string in a private heap

    Quote Originally Posted by Niya View Post
    I'd very much like to know the answer to this as well. Strings are really just binary data interpreted as text so it uses memory just like any other kind of binary data. This error suggests that there is some abstraction in the VB6 runtime that treats strings differently in memory.
    I'll listen in for an answer as well.

    It might be something as simple as what caused it to run out (the very last thing to happen): A request to create a new string? or, A request for other kinds of memory (local variables, etc). But I really don't know.
    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. To all, peace and happiness.

  21. #21
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Creating a large string in a private heap

    Quote Originally Posted by Elroy View Post
    I'll listen in for an answer as well.

    It might be something as simple as what caused it to run out (the very last thing to happen): A request to create a new string?
    I suspect something like this as well.

    I also briefly took a look at the SysAllocString family of functions and they return NULL on the condition that there is insufficient memory. This may mean that a VB6 "Out of string space" is really just saying that a SysAllocString call has failed in the VB6 runtime.
    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

  22. #22

    Thread Starter
    Fanatic Member
    Join Date
    Mar 2019
    Posts
    515

    Re: Creating a large string in a private heap

    Quote Originally Posted by Niya View Post
    I suspect something like this as well.

    I also briefly took a look at the SysAllocString family of functions and they return NULL on the condition that there is insufficient memory. This may mean that a VB6 "Out of string space" is really just saying that a SysAllocString call has failed in the VB6 runtime.
    Heap alloc and virtualalloc also return null although you can configure heap allocations to throw on out of memory. On that note there is a string builder class using heaps that gave me some food for thought although it has a serious bug jn the alloc routine which returns a null pointer if the allocation fails and then tries to copy data to that pointer.

    Boom.

    I must add a note to the code bank entry.

  23. #23

    Thread Starter
    Fanatic Member
    Join Date
    Mar 2019
    Posts
    515

    Re: Creating a large string in a private heap

    @elroy
    Thanks will take a look. I have actually used CreateFileMapping and MapViewOfFile in another project and I thought the address space was inside process limits. Sharing is simply a matter of assigning the same physical pages to virtual pages in multiple processes page tables. In that way virtual memory points to the same physical memory. I remember this from my days as a vms internals support guy.

  24. #24
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: Creating a large string in a private heap

    Quote Originally Posted by vbwins View Post
    Heap alloc and virtualalloc also return null although you can configure heap allocations to throw on out of memory.
    The SysAllocString family of functions allocate BSTR strings which is what VB6 uses as it's native string type. They do a little more than simply allocate memory. It would make sense to throw an "out of string space" error when a call to one of these functions fail. It would more accurately reflect that we are dealing with a higher level abstraction, in this case, a BSTR. That's my instinct anyway.
    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

  25. #25

    Thread Starter
    Fanatic Member
    Join Date
    Mar 2019
    Posts
    515

    Re: Creating a large string in a private heap

    Quote Originally Posted by Niya View Post
    The SysAllocString family of functions allocate BSTR strings which is what VB6 uses as it's native string type. They do a little more than simply allocate memory. It would make sense to throw an "out of string space" error when a call to one of these functions fail. It would more accurately reflect that we are dealing with a higher level abstraction, in this case, a BSTR. That's my instinct anyway.
    Yes I thing you are right. I will catch the error and go back to view the dissambly in windbg which at least will show me what is being called. Tye arguments are beyond me,

  26. #26
    PowerPoster
    Join Date
    Jan 2020
    Posts
    5,538

    Re: Creating a large string in a private heap

    Quote Originally Posted by vbwins View Post
    @elroy
    Thanks will take a look. I have actually used CreateFileMapping and MapViewOfFile in another project and I thought the address space was inside process limits. Sharing is simply a matter of assigning the same physical pages to virtual pages in multiple processes page tables. In that way virtual memory points to the same physical memory. I remember this from my days as a vms internals support guy.
    In this way, you can share your ah, a string variable or a string array.It's just that the best way is to just use it to read, not to use the string destruction method directly.

Tags for this Thread

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