• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 545
  • Last Modified:

MsComm out of stack space - Urgent

I have written a module that reads a GPS from COM2 using the MsComm ocx. The problem is that the module seizes control of the computer and only respond to key presses after some delay. In order to improve this I have a doevents at the beginning of the module, this solves the problem but I then get an 'Out of stack space' error.
I have looked at the call stack and there is my module being called and the caller separated by [non visual basic code] each time repeated many times.
The settings of the MsComm ocx are

                   GpsInput.CommPort = 2
                   GpsInput.InputLen = 1
                   GpsInput.Handshaking = comRTS
                   GpsInput.NullDiscard = True
                   GpsInput.OutBufferSize = 1024
                   GpsInput.InBufferSize = 1024
                   GpsInput.Settings = "4800,n,8,1"
                   GpsInput.SThreshold = 1
                   GpsInput.RTSEnable = True
                   GpsInput.InputMode = comInputModeText
                   GpsInput.DTREnable = True
                   GpsInput.EOFEnable = True

Anybody have any ideas
1 Solution
I do have experience in using doEvent() and having similar encounters. My summary solution to this problem is avoid possible call to the function that call doEvent() during the doEvent().

Endless loop? I've not done it lately, but I believe you can run out of stack space fast if your running an endless loop of gosub type calls. Check for that OR better yet instead of executing your code, go into debug mode and step through the code to see what the process is doing.

Also there can be loads of multi-threading going on since you have used the doevents. The debug process of stepping through the code won't reveal the multi-threading problem directly. For that you may want to resort to using debug.print's to find out where and what is happening. Good luck!
To really identify your problem, you need to give infor on how the module is coded and how it is called.

One thing to look for is the Doevent. Depends on where you put it, but all it does is allow the program to jump of of your reading routine AND EXCUTEING THE ROUTINE TO CALL IT AGAIN.  For example, if you have a timer to call it, it would run your stack space out.

However, you must have something improper in the reading module, since it seize the program.  

What I would do is to make a reading com function, and depending how your data comes to the come port, call the reading function from the MSComm's oncomm event.

'here is my function:
Public Function fReadCOM(theComm As MSComm, WaitOrNot As Boolean, Optional EndCha As String) As String

'   Name:       fReadCOM
'   Author:     Dalin Nie
'   Written:    4/14/97
'   Purpose:

'       This function read one line of data from the RS-232 Com port;
'   Called procedures and functions:

'   Input:  theComm:  Name of the MSComm control which is connected to the port you want to read
'           Wait--Boolean
'                 True:  Keep reading the port until the EndCha is received or timed out
'                        Soutable for contineous recieveing until the endCha after a command is issued, and

'                 False: Just Read once, get whatever is in the put and then get out, suitable
                         ' for use with OnComm event
'            EndCha: the external devices ending characters, usually vbCR or vbCRLF, optional
'   Output: The string it read
Dim lInput As String
Dim lMessage As String
Dim curReading As Single
Dim lLastTwo As String
Dim I As Integer
Dim lTime As Long

On Error GoTo fReadCOMErrHandler

' Set up output of fReadCOM to be blank by default

'add number of lines you expect to read

lMessage = "" 

'Get one Line of Data
'Wait is true, need to wait for the end cha or timed out
If WaitOrNot = True Then
        lTime = Timer
        Do Until Right(lMessage, Len(EndCha)) = EndCha
                If theComm.InBufferCount > 0 Then
                        lInput = theComm.Input
                        lMessage = lMessage + lInput
                    End If ' If frmDeckLayout.Comm1.InBufferCount = dataLen
                'Time out, I use 5 seconds here, change accordingly
                If Timer - lTime > 5 Then Exit Do
' Used for On_Comm Events        
        lMessage = theComm.Input
    End If
     ' strip the EndCha, if what we received is ended with the End Cha
   If Right(lMessage, Len(EndCha)) = EndCha Then
         lMessage = Left(lMessage, Len(lMessage) - Len(EndCha))
     End If
  ' If Has a startcha, strip it too
  ' If Left(lMessage, Len(cStRespBegin)) = cStRespBegin Then
   '     lMessage = Right(lMessage, Len(lMessage) - Len(cStRespBegin))
   '   End If

    fReadCOM = lMessage
    'Put the response to some textbox
    'frmMain.txtCaroResp = lMessage
Exit Function

   fReadCOM = "ERROR" & Err.Number & " " & Err.Description
   ' Oprional gui.

End Function

in the OnComm event of the MSComm control, add:

Dim lstring as string
lString = fReadCom(MSComm1, False)
' now save or display lstring

Let me know if you need more help

Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

gelorupAuthor Commented:
Dialin: I am using part of your code already. The problem is that the GPS squirts sentences at 2 second intervals and I have to try and syncronise this by reading 1 char at a time and then parze out the ones I want, namely GPGGA and GPGLL. It is very crude using the MsComm control and I am triying to find an alternative.
Could you describe the "out of stack" message in details <which stack ?>.

Is it a Windows Error or a VB Error.

gelorupAuthor Commented:
There is no indication of the stack only a runtime error of 28.

Dailin: I pasted your example straight into a sample project and got the same stack error using

lblGPS = fReadCOM(GpsInput, True, "$")

I need complete sentences to parze out the type of message

it sounds to me like your message handling routine is continually getting called, probably by the OnComm event of the MsComm Ocx.

Try setting up your own buffer to store the data

Public Sub HandleComm()
Dim sBuffer as String
Static bBusy as Boolean
      'Copy entire contents of Comms buffer into sbuffer      
      GpsInput.InputLen = 0
      sBuffer = sBuffer & GpsInput.Input

      If bBusy then Exit Sub
 On Error Goto ClearBusy

      bBusy = True

      'Get First Character and remove from buffer
      Dim sChar as String
      sChar = Left$(sBuffer,1)
      sBuffer = Mid$(sBuffer,2)

      { Do Stuff with sChar }

      bBusy = False
      If Len(sBuffer)<>0 or GpsInput.InputCount > 0 then HandleComm

End Sub

Hope this helps
Can you post your code? the routine to read the port, and the way it was called.

You should parse the returned string after you get the data from the port.  Do not read them cha by cha. Read the whole thing when there is something in the buffer.

Stack space is a chuck of memry VB allocate for a procedure/subroutine. Argument and local variable of the procedure will take up (consumes) the stack.  But mostlikely, it is cause by nested call of the same
procedure. For example, if you programaatically change the content of a textbox in it's change event, it can cause endless changes in the textbox.  Other possibilityis that you got too many local variables, but I have not yet encount
such a case in my 7 years of VB programming.

Post your code or email me at Dalin_N@Mailexcite.com if you like. I worked with MSCOmm almost everyday to control robots.
gelorupAuthor Commented:
Sorry, your code ended in a recursive loop which made the problem harder to correct

Try this, Let me know the result:

1. Start a new project

2. Drop a MSComm to your form, Name MSComm1, set the port to the proper port ans settings, in it's OnComm event, add code:
 text1 = text1 & fReadCom(MSComm1, False)

3. Drop a textbox, Named text1, set multiple line to true

4. Drop another Textbox, name it Text2

5. Drop a command, name command1.  in the click event, add
    Static LInNumberofClick as Integer
    LInNumberofClick = LInNumberofClick + 1
    text2.text = "You clicked the Command " & LInNumberofClick  & " times"

6. Add a new procedure to the form, Name it fReadCom, and then paste the code of the funtion (I posted previously) to it;

7. run it.

8 click the command1 a few time.

You should have the readings constantly add to it and be able to click the command.
gelorupAuthor Commented:
Although not directly giving the answer you gave me a direction to re-examine my code structure. The problem is trying to syncronize the satellite data

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now