Page 1 of 2 12 LastLast
Results 1 to 40 of 42

Thread: [RESOLVED] Out of Stack String Space - RichTextBox

  1. #1

    Thread Starter
    PowerPoster SamOscarBrown's Avatar
    Join Date
    Aug 2012
    Location
    NC, USA
    Posts
    9,143

    Resolved [RESOLVED] Out of Stack String Space - RichTextBox

    I have a search routine which looks for certain words or phrases in a RichTextBox. When searching within a 'larger' (but not REALLY large) RTB, I am getting the following error: Out of stack string space. Using the same RTB with fewer occurrences, I do not not experience this. But when searching (and wanting to count) for a certain word (that word should appear around 4500 times in the RTB). The RTB contains around 605,000 characters (not all that huge). But when I attempt the following code to get the exact number of occurrence of that word in the RTB, I get that error on the line bolded in Red:

    Code:
    Private Function FindIt(Box As RichTextBox, Srch As String, Optional start As Long)      Dim retval As Long      
          Dim Source As String    
             Source = UCase(Box.Text)   
             If start = 0 Then start = 1 
                retval = InStr(start, Source, Srch) 
                If retval <> 0 Then  
                   With Box
                      .SelStart = retval - 1
                      .SelLength = Len(Srch)
                      .SelColor = vbRed
                      .SelBold = True
                      .SelLength = 0         
                   End With
                   start = retval + Len(Srch) 
                   FindIt = 1 + FindIt(Box, Srch, start)
                End If
          End Function

  2. #2
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,853

    Re: Out of Stack String Space - RichTextBox

    Hi Sam,

    I don't see anything I'd call a memory leak. However, I do see recursion. With recursion, it's always good to recognize how much memory you're using with your variables. As your function stands, all the variables you used are using additional memory on each recursion.

    You're passing all your arguments as ByRef, but you're still using an additional memory pointer on the stack for each recursive call.

    And, regarding retval and Source, you're creating a separate copy on each recursive call. Actually, it's probably that Source variable that's causing most of your problems. The way you're using it, there's no need to make separate copies on each recursive call. Just make it a module-level variable, and you'll probably solve your problem.

    You could also do the same with retval, and also possibly some of the arguments (such as Box), and your function will still run just fine. From a casual look, it seems that only start needs to be passed on each recursion.

    Good Luck,
    Elroy

    EDIT1: Actually, if you're reluctant to make anything module-level, just clearing that Source variable just before you recurse may also solve your problems. You're done with it at that point:

    Code:
    
                   Source = vbNullString ' <----- New code line !!!
                   FindIt = 1 + FindIt(Box, Srch, start)
    
    
    Last edited by Elroy; Jul 9th, 2019 at 08:56 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.

  3. #3
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Out of Stack String Space - RichTextBox

    Sam, you are keeping a copy of the entire RTB during each recursion

    Suggestion: include another parameter
    Recommend "Source As String" and initiating the search by passing UCase$(RTB1.Text or whatever)

    Use the passed Box parameter for updating the highlighting only
    Last edited by LaVolpe; Jul 9th, 2019 at 09:13 AM.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  4. #4

    Thread Starter
    PowerPoster SamOscarBrown's Avatar
    Join Date
    Aug 2012
    Location
    NC, USA
    Posts
    9,143

    Re: Out of Stack String Space - RichTextBox

    @ Elroy....declaring source in module resulted in a simple crash of the program...no error even given. And setting it to vbNullString actually made no difference...crashed program with no given error.

    @LaVolpe....gonna try what you suggested next.

  5. #5
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: Out of Stack String Space - RichTextBox

    If you're expecting over 4000 matches, that means your pushing over 4000 sets of variables on the stack, and then you have to unwind all those pushes on the stack as well.
    I really don't see a reason this should be a recursive function, as it is wasteful for this purpose.
    Just do a loop in the function to find all the values.
    Code:
      Private Function FindIt2(Box As RichTextbox, Srch As String, Optional start As Long)
        Dim retval As Long
        Dim Source As String
        Dim Count As Long
        
        Source = UCase(Box.Text)
        If start = 0 Then start = 1
            
        retval = InStr(start, Source, Srch)   'find the first match
        Do While retval <> 0
          Count = Count + 1
          With Box
             .SelStart = retval - 1
             .SelLength = Len(Srch)
             .SelColor = vbRed
             .SelBold = True
             .SelLength = 0
          End With
          start = retval + Len(Srch)
          retval = InStr(start, Source, Srch) 'look for additional matches
        Loop
        FindIt2 = Count
      End Function

  6. #6

    Thread Starter
    PowerPoster SamOscarBrown's Avatar
    Join Date
    Aug 2012
    Location
    NC, USA
    Posts
    9,143

    Re: Out of Stack String Space - RichTextBox

    @LaVolpe...

    I call the following function like this:

    Code:
        Dim numOccurences As Double
        numOccurences = FindIt(frmSearchResults.rtb1, UCase$(frmSearchResults.rtb1.Text), UCase(Text2.Text), 1)
    Function: NOTE: I commented out highlight code temporarily

    Code:
    Private Function FindIt(Box As RichTextBox, Source As String, Srch As String, Optional start As Long)      Dim retval As Long
             If start = 0 Then start = 1
                retval = InStr(start, Source, Srch)
                If retval <> 0 Then
    '               With Box
    '                  .SelStart = retval - 1
    '                  .SelLength = Len(Srch)
    '                  .SelColor = vbRed
    '                  .SelBold = True
    '                  .SelLength = 0
    '               End With
                   start = retval + Len(Srch)
                   FindIt = 1 + FindIt(Box, UCase$(frmSearchResults.rtb1.Text), Srch, start)
                End If
    End Function
    I get an OUT OF MEMORY Error on the bolded red line (recursive portion).

    @ passel....your suggestion next
    Last edited by SamOscarBrown; Jul 9th, 2019 at 09:43 AM. Reason: misspelled 'your'

  7. #7

    Thread Starter
    PowerPoster SamOscarBrown's Avatar
    Join Date
    Aug 2012
    Location
    NC, USA
    Posts
    9,143

    Re: Out of Stack String Space - RichTextBox

    @ passel....yup...that worked fine. Found the 4531 occurrences of the search word in the 3910 lines of the RTB.

    Appreciate the advice to not use a recursive function...had thought it necessary when I first built this thing about 8 years ago.

    But, at LaVolpe and Elroy...would still like to determine why the recursive functions (as shown previously) errored or crashed, in case I want to use something similar in the future.

    Sam

  8. #8
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Out of Stack String Space - RichTextBox

    Quote Originally Posted by SamOscarBrown View Post
    @LaVolpe...

    I call the following function like this...

    I get an OUT OF MEMORY Error on the bolded red line (recursive portion).
    Yep, you didn't understand what I was trying to say & I didn't explain it well enough.

    I know you have this resolved, but I just wanted to update the thread for future use (if any). Changes in blue
    Code:
        Dim numOccurences As Double
        numOccurences = FindIt(frmSearchResults.rtb1, UCase$(frmSearchResults.rtb1.Text), UCase(Text2.Text), 1)
    Function: NOTE: I commented out highlight code temporarily

    Code:
    Private Function FindIt(Box As RichTextBox, Source As String, Srch As String, Optional start As Long)      Dim retval As Long
             If start = 0 Then start = 1
                retval = InStr(start, Source, Srch)
                If retval <> 0 Then
    '               With Box
    '                  .SelStart = retval - 1
    '                  .SelLength = Len(Srch)
    '                  .SelColor = vbRed
    '                  .SelBold = True
    '                  .SelLength = 0
    '               End With
                   start = retval + Len(Srch)
                   FindIt = 1 + FindIt(Box, Source, Srch, start)
                End If
    End Function
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  9. #9
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: Out of Stack String Space - RichTextBox

    It crashes because of the massive amount of memory you're using.

    FindIt = 1 + FindIt(Box, UCase$(frmSearchResults.rtb1.Text), Srch, start)

    In the case above, you're creating a uppercase version of your text string for each recursive call.
    You said you had about 605,000 characters, so assume that is 1,210,000 bytes per call.
    You need to call the routine 4531 times, so 4531 * 1,210,000 = 5,482,510,000 bytes of memory (about 5.5 GB).
    Since VB6 normally only has a 2GB executable address space, you have a fair amount less than 2GB space available for Strings, so you run out of memory long before you can call the routine the number of times required.

    A recursive routine normally acts on some external data repeatedly, so the values preserved on the stack for each recursive call is fairly small, usually just pointers, counters, and status type variable that keep track of what is being processed at each level.
    Recursion is good for traversing a hierarchy, like calculating moves, or paths, etc...

    In your case, you're doing a straight forward linear search of a large string, so real benefit to having it a recursive function as there are no conditional branches and other paths to explore. No reason to keep a history of your search values in order to unwind to an earlier level and take a different direction.

    {edit}
    Since LaVolpe has already explained what he meant, I've removed that from this post.
    With that change, you now only create the string once, and you are passing a reference to that string (the same way you're passing a reference to the textbox) with each call, so instead of a million+ bytes per call, you are only adding a small amount of bytes per call (whatever a reference for a string is, which may just be a 4 byte pointer to a string structure, which points to the string).
    That would still mean 4 * 4531 bytes used by the recursive process for that parameter, and the same for the textbox parameter, but at least that is very manageable, although an unnecessary overhead without any benefit in this case.
    Last edited by passel; Jul 9th, 2019 at 10:24 AM.

  10. #10

    Thread Starter
    PowerPoster SamOscarBrown's Avatar
    Join Date
    Aug 2012
    Location
    NC, USA
    Posts
    9,143

    Re: [RESOLVED] Out of Stack String Space - RichTextBox

    @ LaVolpe....re-tried what you suggested. Crashed program (because of what passel is saying, I am sure). You explained it fine the first time...I just didn't pay attention. I called the function the first time properly, but in the recursive section, I simply copied the UCASE$ thingy instead of using Source (duh---just wasn't thinking).

    @passel...understand. That IS a fair amount of memory usage! Your explanation is back to the basics I should have recalled from years ago, but didn't.

    So, if I don't keep a history of search values each time in a recursive function, how do I do that? I thought Elroy's suggestion setting Source to vbNullString would have done it.

  11. #11
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,853

    Re: [RESOLVED] Out of Stack String Space - RichTextBox

    I'm probably not testing quite as much text as you are, Sam ... but just setting Source to vbNullString works for me.

    I also declared your FindIt function as a Long rather than letting it default to Variant.

    My test is attached.


    EDIT1: I also searched for "A" rather than "AND". It found 1212 occurrences, but still worked just fine.
    Attached Files Attached Files
    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.

  12. #12
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: [RESOLVED] Out of Stack String Space - RichTextBox

    Quote Originally Posted by SamOscarBrown View Post
    ...
    So, if I don't keep a history of search values each time in a recursive function, how do I do that? I thought Elroy's suggestion setting Source to vbNullString would have done it.
    I don't know when the data associated with a reference is cleaned up in VB6.
    The UCase function should create a large string in memory, then return a reference to it, which you assign to Source.

    Later, you set Source to vbNullString, so you've disconnected the reference to the large string.
    Since the large string should no longer have any variable referencing it, it should probably be "cleaned up", and the memory recovered, but I don't know when that occurs. It might be something that is done between user code events, i.e. once you leave a sub, housekeeping chores are run, and objects without references are disposed of.

    Since you didn't leave the sub, but had the sub call itself, then I can imagine that the unreferenced string is still there, but "flagged" for disposal. So, although you set your reference to the string to 0, it isn't getting rid of the string itself yet, so you eventually end up crashing in yet another way, which perhaps doesn't trigger the Out of Memory exception because of the nature of the error, although it seems like it should.

    Mostly supposition on my part, not a known fact.

    p.s. I can't look at Elroy's test because I'm at work and I'm blocked from downloading from the site, but I suspect that Elroy's string might be short enough, that it doesn't run out of memory before the recursion is complete, and then as each level of recursion exits it's sub, the string memory is recovered from each of those levels because of the string reference having been set to vbNullString.
    Again, a supposition, no testing done.
    Last edited by passel; Jul 9th, 2019 at 12:19 PM.

  13. #13
    Fanatic Member
    Join Date
    Feb 2019
    Posts
    706

    Re: [RESOLVED] Out of Stack String Space - RichTextBox

    FYI, you can color text without touching user's selection, see this thread, or google this forum for "Tom dilettante".

  14. #14

    Thread Starter
    PowerPoster SamOscarBrown's Avatar
    Join Date
    Aug 2012
    Location
    NC, USA
    Posts
    9,143

    Re: [RESOLVED] Out of Stack String Space - RichTextBox

    I'll 'gin' up an exportable example (using the recursion function I started with)...and if it still crashes the program, I'll post it. I'll then try it with Elroy's code (but with my rtb data) and see.

    @passel...that certainly makes some sense...that is, when a reference is 'cleaned up'.

    Sam

  15. #15
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,853

    Re: [RESOLVED] Out of Stack String Space - RichTextBox

    What Passel outlines sounds more like managed code. I'll admit that I'm not totally sure how memory is managed for VB6 (or any COM based 32-bit application), but I'm under the impression that things are done immediately (such as instantiation/un-instantiation, memory requests, memory releases, and the like). In other words, when memory is to be released, our thread doesn't continue until that task is completed.

    It's always been a puzzle to me how holes in memory are eventually squashed, but maybe they're not. Or maybe Windows just keeps track of things in a way that just fills them whenever something else will fit into them. I'd be delighted if someone else would outline that a bit more.

    Also, every time I say the words "garbage collector" (like we had in the old DOS days), I get pounced on.

    I do know that nothing seems to move around in memory, allowing us to trust our memory pointers for extended periods of time. So, I'm not totally sure.
    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.

  16. #16
    PowerPoster ChrisE's Avatar
    Join Date
    Jun 2017
    Location
    Frankfurt
    Posts
    3,042

    Re: [RESOLVED] Out of Stack String Space - RichTextBox

    Hi Sam,

    another option may be using Regex, the File I used had 55080 words and the find was 2214


    here the sample
    Code:
    Option Explicit
    
    
    Private pRegEx As Object
    
    Public Property Get oRegex() As Object
       If (pRegEx Is Nothing) Then
          Set pRegEx = CreateObject("Vbscript.Regexp")
       End If
       Set oRegex = pRegEx
    End Property
    
    Public Function ReadFile(ByRef Path As String) As String
       Dim FileNr As Long
       On Error Resume Next
       If FileLen(Path) = 0 Then Exit Function
       On Error GoTo 0
       FileNr = FreeFile
       Open Path For Binary As #FileNr
       ReadFile = Space$(LOF(FileNr))
       Get #FileNr, , ReadFile
       Close #FileNr
    End Function
    
    Private Sub Command1_Click()
    'the file has 55080 words and found 2214
    RichTextBox1.Text = ReadFile("E:\book04.txt")
    End Sub
    
    Private Sub Command2_Click()
     Dim oRegex As Object
      Dim m As Object
      Dim strPattern As String
      Dim i As Long
     
      strPattern = " and " '<- the word to find, notice space before/after the word
      If Len(Trim(strPattern)) = 0 Then Exit Sub
     
      On Error GoTo ErrHandler
      'set color to Black
      With RichTextBox1
        .SelStart = 1
        .SelLength = Len(.Text)
        .SelColor = vbBlack
      End With
     
      ' "Regular-Expression"-Objekt
      Set oRegex = CreateObject("VBScript.RegExp")
      With oRegex
        .Pattern = strPattern
        .Global = True
        ' --> go threw all matches
       i = 0
        For Each m In .Execute(RichTextBox1.Text)
          ' --> found items to Red
          With RichTextBox1
            .SelStart = m.FirstIndex
            .SelLength = m.Length
            .SelColor = vbRed
          End With
          '--> Counter
           i = i + 1
        Next
      End With
     Text1.Text = "the Count is : " & i
      ' --> kill Regex Object
      Set oRegex = Nothing
      Set m = Nothing
      Exit Sub
     
    ErrHandler:
      MsgBox Err.Description & vbCrLf & Err.Number, vbCritical + vbOKOnly, "Error"
      Err.Clear
    End Sub
    hth
    to hunt a species to extinction is not logical !
    since 2010 the number of Tigers are rising again in 2016 - 3900 were counted. with Baby Callas it's 3901, my wife and I had 2-3 months the privilege of raising a Baby Tiger.

  17. #17
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: [RESOLVED] Out of Stack String Space - RichTextBox

    BSTRs have a complex allocation mechanism that was designed to improve performance. Some of the complexity is described in:

    Caches are nice, but they confuse memory leak detection tools

    So the memory used for modern VB (dynamic) Strings is managed in a more complex manner than most other data types.

  18. #18
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: [RESOLVED] Out of Stack String Space - RichTextBox

    Using UCase$() on a large text value can have both benefits and limitations.

    It can be faster to do a case-insensitive search on but...

    First you eat twice the memory by having two copies around.

    Second you lose all of the advantages of orthography-sensitive comparisons, for example handling ligature and digraph comparisons properly.


    I'm not sure there is any version of regex smart enough to do the job properly. They are simple tools meant to help in slow and clunky shell scripting languages, not something a real compiled program would ever use.

  19. #19
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,853

    Re: [RESOLVED] Out of Stack String Space - RichTextBox

    Ok, some more thoughts on all of this.

    First, the .Text property of the RTB is already a String:

    Name:  RtbText.png
Views: 391
Size:  14.5 KB

    It's not clear if that's a function returning a string that's built each time the function is called, or possibly a string that already exists inside the RTB code. If it already exists, then just directly using that .Text property would be better than copying it before we use it. However, that'd take some timing tests to figure out. (Basically, we'd just need to test a simple InStr with a string versus InStr with a RTB.Text, both in loops to build enough time to be meaningful.)

    ------

    And second, if we're willing to use the SHLWAPI.DLL library, rather than VB6's InStr, it seems that we could do ourselves some large favors:

    Code:
    
    '
    ' https://docs.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-strstrw
    Private Declare Function StrStrW Lib "SHLWAPI" (ByVal lpFirst As Long, ByVal lpSrch As Long) As Long    ' Case sensitive.
    '
    ' https://docs.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-strstriw
    Private Declare Function StrStrIW Lib "SHLWAPI" (ByVal lpFirst As Long, ByVal lpSrch As Long) As Long   ' NOT case sensitive.
    '
    
    

    We'd want to make sure to use the ...W versions of the calls so we're not making yet more copies of our string. But, by adding offsets to lpFirst, we could effectively accomplish the same thing that the start argument to InStr is accomplishing. It doesn't seem that it would take that much to develop a nice case-insensitive InStr alternative.


    Just Spit-Balling,
    Elroy
    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.

  20. #20
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: [RESOLVED] Out of Stack String Space - RichTextBox

    The Text property value has to be manufactured each time it is called.

    InStr already has the vbTextCompare option. It looks like this is one place where you can provide a valid LCID as the option to get text comparison using the rules of that locale instead of the user's locale.
    Last edited by dilettante; Jul 10th, 2019 at 10:07 AM.

  21. #21
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,853

    Re: [RESOLVED] Out of Stack String Space - RichTextBox

    Actually, looking at the OP code, Sam, you'd certainly be doing yourself a favor if you replaced the...

    Code:
    
    retval = InStr(start, Source, Srch)
    

    ... line of code with ...

    Code:
    
    retval = InStr(start, UCase(Box.Text), Srch)
    

    ... and then eliminate the Source variable altogether. That way, the string passed into InStr is just a VB6 temp string that VB6 will clean-up. And it will almost certainly reduce the thrashing of memory at least a bit.

    I might still do more testing on my ideas in my last post.

    Best Regards,
    Elroy
    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.

  22. #22
    Fanatic Member
    Join Date
    Feb 2019
    Posts
    706

    Re: [RESOLVED] Out of Stack String Space - RichTextBox

    Quote Originally Posted by Elroy View Post
    And second, if we're willing to use the SHLWAPI.DLL library, rather than VB6's InStr, it seems that we could do ourselves some large favors:

    Code:
    
    '
    ' https://docs.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-strstrw
    Private Declare Function StrStrW Lib "SHLWAPI" (ByVal lpFirst As Long, ByVal lpSrch As Long) As Long    ' Case sensitive.
    '
    ' https://docs.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-strstriw
    Private Declare Function StrStrIW Lib "SHLWAPI" (ByVal lpFirst As Long, ByVal lpSrch As Long) As Long   ' NOT case sensitive.
    '
    
    

    We'd want to make sure to use the ...W versions of the calls so we're not making yet more copies of our string. But, by adding offsets to lpFirst, we could effectively accomplish the same thing that the start argument to InStr is accomplishing. It doesn't seem that it would take that much to develop a nice case-insensitive InStr alternative.


    Just Spit-Balling,
    Elroy
    StrStrI probably only considers US English, but I am not sure, so it may not have the same behavior as InStr(vbTextCompare).

  23. #23
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,853

    Re: [RESOLVED] Out of Stack String Space - RichTextBox

    Quote Originally Posted by dilettante View Post
    The Text property value has to be manufactured each time it is called.
    I'll test in just a moment.

    Quote Originally Posted by dilettante View Post
    InStr already has the vbTextCompare option. It looks like this is one place where you can provide a valid LCID as the option to get text comparison using the rules of that locale instead of the user's locale.
    I haven't messed with vbTextCompare, but that doesn't give us case-insensitivity, does it?
    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.

  24. #24
    Fanatic Member
    Join Date
    Feb 2019
    Posts
    706

    Re: [RESOLVED] Out of Stack String Space - RichTextBox

    Quote Originally Posted by Elroy View Post
    I haven't messed with vbTextCompare, but that doesn't give us case-insensitivity, does it?
    It does, plus handling ligature and digraph comparisons as dilettante mentioned.

    P.S.: VB's StrComp() function maybe using CompareString() API function internally, but I am not sure.

  25. #25
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,853

    Re: [RESOLVED] Out of Stack String Space - RichTextBox

    Ok, based on that information, Sam, the following is a pretty big improvement on your original function:

    Code:
    
    Private Function FindIt(Box As RichTextBox, Srch As String, Optional start As Long) As Long
        Dim retval As Long
        '
        If start = 0 Then start = 1
            retval = InStr(start, Box.Text, Srch, vbTextCompare)
            If retval <> 0 Then
            With Box
                .SelStart = retval - 1
                .SelLength = Len(Srch)
                .SelColor = vbRed
                .SelBold = True
                .SelLength = 0
            End With
            start = retval + Len(Srch)
            FindIt = 1 + FindIt(Box, Srch, start)
        End If
    End Function
    
    

    Notice that the Source variable and the call to UCase$() are both gone. This eliminates a considerable amount of memory thrashing. I'm still calling Box.Text on each recursion, but you were already doing that. In a moment, I'll do a timing test to see how much of a speed-penalty we're taking for multiple calls to Box.Text. If they're severe, an alternative would be to make your Source variable a module-level variable, set it before calling FindIt, and then use this module-level variable within FindIt. But again, I'll test.
    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.

  26. #26
    PowerPoster ChrisE's Avatar
    Join Date
    Jun 2017
    Location
    Frankfurt
    Posts
    3,042

    Re: [RESOLVED] Out of Stack String Space - RichTextBox

    Hi,

    I'll have another go

    Code:
    Private Sub Command6_Click()
    Text1.Text = CountStringInString(RichTextBox1.Text, " and ", False)
    End Sub
    
    
    Public Function CountStringInString(Text As String, SearchFor As String, _
                                        Optional ComapareAsText As Boolean = False) As Long
    
       Dim i As Long, j As Long, z As Long
       Dim s As String, s1 As String
          If ComapareAsText Then
             s = UCase$(Text)
             s1 = UCase$(SearchFor)
          Else
             s = Text
             s1 = SearchFor
          End If
          i = 1
          Do
             j = InStr(i, s, s1, vbBinaryCompare)
             If j = 0 Then
                Exit Do
             End If
              With RichTextBox1
                   .SelStart = j - 1
                   .SelLength = Len(s1)
                   .SelColor = vbRed
                   .SelBold = True
                   .SelLength = 0
                End With
             i = j + Len(s1)
             z = z + 1
          Loop
          CountStringInString = z
    End Function
    to hunt a species to extinction is not logical !
    since 2010 the number of Tigers are rising again in 2016 - 3900 were counted. with Baby Callas it's 3901, my wife and I had 2-3 months the privilege of raising a Baby Tiger.

  27. #27
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: [RESOLVED] Out of Stack String Space - RichTextBox

    I don't know what he wants to search but it seems like the last time this came up it was a 5MB to 7MB Christian Bible stored on disk as ANSI RTF.

    Edit: Ok, he says something like 605,000 characters now.

    I just can't see how it makes sense extract this as a Unicode String over and over again. Why would you even think so?
    Last edited by dilettante; Jul 10th, 2019 at 10:41 AM.

  28. #28
    PowerPoster ChrisE's Avatar
    Join Date
    Jun 2017
    Location
    Frankfurt
    Posts
    3,042

    Re: [RESOLVED] Out of Stack String Space - RichTextBox

    Quote Originally Posted by dilettante View Post
    I don't know what he wants to search but it seems like the last time this came up it was a 5MB to 7MB Christian Bible stored on disk as ANSI RTF.

    I just can't see how it makes sense extract this as a Unicode String over and over again. Why would you even think so?
    I think he wan't to load the File into a RTB and mark his search Item RED, or I got the question wrong ?
    to hunt a species to extinction is not logical !
    since 2010 the number of Tigers are rising again in 2016 - 3900 were counted. with Baby Callas it's 3901, my wife and I had 2-3 months the privilege of raising a Baby Tiger.

  29. #29
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: [RESOLVED] Out of Stack String Space - RichTextBox

    What kind of time do you expect on searches, what's your goal?

  30. #30
    PowerPoster ChrisE's Avatar
    Join Date
    Jun 2017
    Location
    Frankfurt
    Posts
    3,042

    Re: [RESOLVED] Out of Stack String Space - RichTextBox

    the search isn't the problem, he want's to set Colors in the RTB,for all I know there could/will be more than one word
    to search with diffrent Colors
    to hunt a species to extinction is not logical !
    since 2010 the number of Tigers are rising again in 2016 - 3900 were counted. with Baby Callas it's 3901, my wife and I had 2-3 months the privilege of raising a Baby Tiger.

  31. #31
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,853

    Re: [RESOLVED] Out of Stack String Space - RichTextBox

    Ok, we clearly don't want to call Box.Text over and over:

    Name:  Timings.png
Views: 424
Size:  28.7 KB

    We take ~100 fold hit for calling the Box.Text property over and over, as opposed to just calling it once and setting it in a string.

    I've attached my timing test program. But basically, the loops look something like this:

    Code:
    
    Private Sub Command1_Click()
    
        Dim dStringTime As Double
        Dim dTextPropTime As Double
    
    
        dStringTime = TestWithString
        dTextPropTime = TestWithTextProp
    
    
        MsgBox "String time:      " & Format$(dStringTime, "0.00000000") & vbCrLf & _
               "Text prop time: " & Format$(dTextPropTime, "0.00000000")
    
    
    
    End Sub
    
    Private Function TestWithString() As Double
        Dim dStart As Double
        Dim dFinish As Double
        Dim i As Long
        Dim j As Long
        '
        dStart = TimerEx
            For i = 1 To LoopIterations
                j = InStr(100, s, "and")
            Next
        dFinish = TimerEx
        '
        TestWithString = dFinish - dStart
    End Function
    
    Private Function TestWithTextProp() As Double
        Dim dStart As Double
        Dim dFinish As Double
        Dim i As Long
        Dim j As Long
        '
        dStart = TimerEx
            For i = 1 To LoopIterations
                j = InStr(100, RichTextBox1.Text, "and")
            Next
        dFinish = TimerEx
        '
        TestWithTextProp = dFinish - dStart
    End Function
    
    

    Therefore, sticking with the OP's recursion theme, we could further improve with something like the following:

    Code:
    
    Private Function FindIt(Box As RichTextBox, Srch As String, Optional Start As Long) As Long
        Dim Retval      As Long
        Static Source   As String
        '
        If Start = 0& Then
            Source = Box.Text                               ' Only call Box.Text on our first time in.
            Start = 1&
        End If
        '
        Retval = InStr(Start, Source, Srch, vbTextCompare)  ' We use vbTextCompare to be case insensitive.
        If Retval <> 0 Then
            With Box
                .SelStart = Retval - 1&
                .SelLength = Len(Srch)
                .SelColor = vbRed
                .SelBold = True
                .SelLength = 0&
            End With
            Start = Retval + Len(Srch)
            FindIt = 1& + FindIt(Box, Srch, Start)
        End If
    End Function
    
    

    I also cleaned up more of the indentation.

    Sticking with the recursion, I think that's about as good as it gets.
    Attached Files Attached Files
    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.

  32. #32

    Thread Starter
    PowerPoster SamOscarBrown's Avatar
    Join Date
    Aug 2012
    Location
    NC, USA
    Posts
    9,143

    Re: [RESOLVED] Out of Stack String Space - RichTextBox

    Hmmm...just took a break from digging up several old tree stumps in a dried up lake bed, now getting ready to mow 3 acres...so decided to 'check in'.

    Very interesting comments and code (although I haven't yet had the time to 'play'). But to clarify a bit...

    Yes, my 'Bible' program (I have several versions in an Access Database) is what includes that function. I allow a search routine based on A word, AN exact Phrase, and a Phrase with wildcards. Options to search are the entire Bible (one version at a time), the OT, the NT, the current BOOK being viewed, and the current CHAPTER being viewed. It works well when the number of occurrences is not very large. But when one searches for 'God' (or 'god'---I do not distinguish for capitalization) in an ENTIRE Bible, the program crashed (until I used the code provided by passel). The reason I know how many occurrences should have been id'd, is because I successfully (with the old function) searched both testaments separately.

    I am NOT concerned with the amount of time it takes to do the searches.

    I use the RTB to display in RED the searched for word or phrase to display to the user. (I also have copy-paste functions to capture Scripture(s) from the RTB).

    I hope that answers all the questions above. I am certain there are other methods of doing this, but that is what I put together a few years ago...Just now getting around to allowing searches that return a lot of occurrences.

    Well, off to the Husqvarna! Back to this tomorrow....Church tonight.

  33. #33

    Thread Starter
    PowerPoster SamOscarBrown's Avatar
    Join Date
    Aug 2012
    Location
    NC, USA
    Posts
    9,143

    Re: [RESOLVED] Out of Stack String Space - RichTextBox

    Rain started. Got a minute or two. Elroy, substituted "Box.Text" in lieu of 'Source"---only found one occurrence in my 'God search'.

    So, to better explain, maybe, I ALREADY have all the Scriptures added to the RichTextBox by a query to my tables based upon if the search word/phrase is found within the Scripture. All I really want to do then is search the RTB for the occurrences and set them Bold Red. That's all.

    Dinner is ready, so will look at some of your suggestions tomorrow or late tonight.

    Thanks all for your interest and guidance.

  34. #34
    Hyperactive Member
    Join Date
    Mar 2019
    Posts
    416

    Re: [RESOLVED] Out of Stack String Space - RichTextBox

    '
    ' https://docs.microsoft.com/en-us/win...hlwapi-strstrw
    Private Declare Function StrStrW Lib "SHLWAPI" (ByVal lpFirst As Long, ByVal lpSrch As Long) As Long ' Case sensitive.
    '
    ' https://docs.microsoft.com/en-us/win...lwapi-strstriw
    Private Declare Function StrStrIW Lib "SHLWAPI" (ByVal lpFirst As Long, ByVal lpSrch As Long) As Long ' NOT case sensitive.


    Are these faster than instr?

  35. #35
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: [RESOLVED] Out of Stack String Space - RichTextBox

    I'm positive we have been down this very same road before. In fact I found the old solution I had proposed. I'm surprised nobody has even suggested this approach in this new thread. It's pretty basic to the RTB and well documented.

    Here's a rewrite from scratch, with a sample file included. It makes use of the RTB's Find method and a simple loop:

    Name:  sshot.png
Views: 345
Size:  8.5 KB

    Note that within paragraphs (no hard line-break) it can find phrases that wrap when printed or displayed. If you have broken things up into lines for some reason you're screwed. The paragraph break causes mismatches for those cases.

    Since we didn't retain a "record" of each hit on the search text we must call Find again to step to the next, next, next hit. We must also Find again to "reset." If you retain a log of the position of each hit in an array or something "next" and "reset" could be quicker.


    If performance really is an issue (if you search for a word or phrase that occurs a lot search/reset can slow down a lot) using TOM instead of the RTB.Find might be a little quicker. But most of the performance issues seem to come from inserting formatting, not so much searching.
    Attached Files Attached Files
    Last edited by dilettante; Jul 11th, 2019 at 02:17 PM.

  36. #36

    Thread Starter
    PowerPoster SamOscarBrown's Avatar
    Join Date
    Aug 2012
    Location
    NC, USA
    Posts
    9,143

    Re: [RESOLVED] Out of Stack String Space - RichTextBox

    dile...I am sure we've traveled along this path in the past...but at my age, who can remember? MAYBE we did discuss this long ago with this exact same problem. And if so, I obviously didn't implement anyone's suggestions.
    As far as 'lines', I have each individual verse on a line in the RTB, put there by a query to my DB, i.e. the query finds every verse that has the search word in it and adds it to the RTB. Hence, no need to worry about 'wrapping'. When searching for "God", for example, my query returns 3910 verses. So, once they are in the RTB, I use that 'find' function just to 're-find' the word/phrase so I can highlight and embolden it. And, in those 3910 verses (in the Bible version I am doing my testing with), finds 'God' 4531 times.

    I haven't yet downloaded your example, but will do that in next couple of days. (I may also have somewhere on this computer an example you may have posted in one of my threads concerning the RTB find method.)
    After typing this little explanation, I wonder if, seeing as how my db query already found the verses with the search word, would there be a way WHEN I ADD THE VERSE TO THE RTB, to, at that point, bold and highlight the search word...that would preclude having to once again search the RTB.
    Again, performance, at this point, is not an issue. Yes, it takes a few seconds in MY search routine, but it doesn't matter---it is MY personal program for my personal use.
    And as always, to you dile, and all the other helpful folks out there, thanks for taking the time to TRY to 'teach an old dog new tricks'.

  37. #37
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: [RESOLVED] Out of Stack String Space - RichTextBox

    Well my small contribution was really just to consider the RTF.Find method.

    If each verse retrieved is just plain text with no RTF markup in it I suppose you might use InStr and friends to find target text occurrences and wrap them in markup text to create an RTF "scrap" that can be appended using the RTB.SelRTF property. I'm not sure what the advantage might be though. It seems like more work.

  38. #38
    PowerPoster ChrisE's Avatar
    Join Date
    Jun 2017
    Location
    Frankfurt
    Posts
    3,042

    Re: [RESOLVED] Out of Stack String Space - RichTextBox

    I think dilettante is right with the RTF.Find method, but if you(sam) say, the few seconds more, it takes for
    the search doesn' matter ... it's up to you
    to hunt a species to extinction is not logical !
    since 2010 the number of Tigers are rising again in 2016 - 3900 were counted. with Baby Callas it's 3901, my wife and I had 2-3 months the privilege of raising a Baby Tiger.

  39. #39

    Thread Starter
    PowerPoster SamOscarBrown's Avatar
    Join Date
    Aug 2012
    Location
    NC, USA
    Posts
    9,143

    Re: [RESOLVED] Out of Stack String Space - RichTextBox

    Thx both...yeah, time doesn't matter. I WILL try the .Find method shortly. Will report back on success/stupidity on my part/better or worst, etc.

    If this were a commercial product, I'd spend a LOT more time studying various methods, options and tools to make it work faster (and correctly, of course), but seeing as how it is just for my use (or maybe a friend's), I'll not spend much more on it....after looking at the .Find method of the RTB.

  40. #40
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: [RESOLVED] Out of Stack String Space - RichTextBox

    RTB.Find is pretty fast actually. Take my demo above and alter it:

    Code:
    Private Sub cmdSearch_Click()
        Dim SearchAt As Long
    
        MousePointer = vbHourglass
        With txtSearchFor
            .Enabled = False
            SearchFor = .Text
        End With
        HitCount = 0
        With rtbText
            .Visible = False
            Do
                SearchAt = .Find(SearchFor, SearchAt, , rtfWholeWord)
                If SearchAt < 0 Then Exit Do
                SearchAt = SearchAt + Len(SearchFor)
                HitCount = HitCount + 1
    '            .SelColor = vbRed
    '            .SelBold = True
            Loop
            .SelStart = 0
            If HitCount = 0 Then
                lblStatus.Caption = "Found 0 occurrences"
            Else
                'Bring first hit into view by finding it again:
                NextSrearchAt = .Find(SearchFor, 0, , rtfWholeWord) + Len(SearchFor)
                HitNumber = 1
                lblStatus.Caption = "1 of " & Format$(HitCount, "#,##0") _
                                  & " occurrence" & IIf(HitCount = 1, vbNullString, "s")
                
                If HitCount > 1 Then
                    cmdNextHit.Enabled = True
                    cmdNextHit.SetFocus
                End If
            End If
            .Visible = True
        End With
        cmdReset.Enabled = True
        cmdSearch.Enabled = False
        MousePointer = vbDefault
    End Sub
    Now it won't try to highlight the hits and it zips right along by comparison. Choose something common like "and" to search for. The more hits the longer things take.

    Searching isn't really the performance problem, inserting and removing the RTF markup takes far longer in the unaltered version of the program.

Page 1 of 2 12 LastLast

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