Silverfrost Forums

Welcome to our forums

Stack error

5 Dec 2015 12:25 #17066

mecej4,

Yes, I was fully aware that the ESP reflects the stack pointer in the called routine. Rather than get the actual value at the point of call, I chose to use the fact that, relatively, the stack should be the same regardless of the actual value. In this way, I can more easily remove the trace simply by changing the one routine (my_routine) to always return the same value.

5 Dec 2015 7:35 #17067

I expanded the code trials a bit more, putting in a few variations, explicit use of the non-blank length (len_trim), etc.

The results, while clear, are not consistent. Using len_trim() to set the character count is no better than using trim(), but using trim() then concatenating those results appears to work just fine.

Code:

!FTN95 application...
    PROGRAM main
    external my_routine
    integer*4 my_routine
    character*256 raw_data
    character*12 quad
    character*4 state
    integer i,j
    logid=1
    quad='hndsh'
    state='ky'
    raw_data = ' xyz'
99000 format(z16)
    write(*,99000)my_routine()
    print *,'Use 2 trim() calls'
	  WRITE(*,55055)trim(quad),trim(state),'0'
55055 format(a,a,a)
    write(*,99000)my_routine()
    print *,'Trim and len_trim',trim(quad),logid,state(1:len_trim(state))
    write(*,99000)my_routine()
    print *,'Use len_trim',quad(1:len_trim(quad)),logid,state(1:len_trim(state))
    write(*,99000)my_routine()
    i=len_trim(quad)
    j=len_trim(state)
    print *,'Used len_trim to get lexplicit engths'
    write(*,99000)my_routine()
   	print *,'Use explicit lengths',quad(1:i),logid,state(1:j)
    write(*,99000)my_routine()
	raw_data = quad//state//trim(raw_data)
    print *,'Concatenation only as assignment'
    write(*,99000)my_routine()
    print *,'concat trims and print',trim(quad)//trim(state)!//trim(raw_data)
    write(*,99000)my_routine()
    print *,'Just plain print',quad,state
    write(*,99000)my_routine()
    print *,'trim only quad',trim(quad),state
    write(*,99000)my_routine()
    print *,'trim only quad, output state twice',trim(quad),state,state
    write(*,99000)my_routine()
    print *,'len_trim only quad',quad(1:i),state
    write(*,99000)my_routine()
        
    END PROGRAM main
	integer function my_routine()
    integer i
    code
    mov eax%,esp%
    mov i,eax%
    edoc
    my_routine = i
    return
    end

Results:

         360F578
 Use 2 trim() calls
hndshky0
         360F568
 Trim and len_trimhndsh           1ky
         360F558
 Use len_trimhndsh           1ky
         360F548
 Used len_trim to get lexplicit engths
         360F548
 Use explicit lengthshndsh           1ky
         360F538
 Concatenation only as assignment
         360F538
 concat trims and printhndshky
         360F538
 Just plain printhndsh       ky
         360F538
 trim only quadhndshky
         360F538
 trim only quad, output state twicehndshky  ky
         360F538
 len_trim only quadhndshky
         360F538

By trying different numbers of trim() strings and other variables, the number of variables that affect the stack (i.e. the trim() or len_trim() ones) are affected by the number of successfully output data of other types, including character data. Given the right number of each, the stack is unaffected.

So, for me, at least at this time, there is no good fix for the code, other than using the /RELEASE version.

11 Dec 2015 11:54 #17077

Paul, I'm wondering if you might have tried the code and have seen the same results that I have.

Bill

12 Dec 2015 7:49 #17078

Bill

I have not tried your code but will aim to do so on Monday. Having said that, from a brief look at your post, I am not clear about what I will be looking for.

12 Dec 2015 1:08 #17080

Paul, fair enough.

The basis for the request is that , while in a function/subroutine, the stack pointer should remain at the same value. However, using the sample program, you will find that, for whatever reason and only when running /CHECKMATE, the stack gets corrupted. Specifically, the stack will decrement under specific circumstances. My issue was that as my original code was running, it was performing tens/hundreds of thousands of the suspect IO statements until a stack overflow exception was generated. Running the same test code under /RELEASE will show that the stack pointer remains the same throughout the run. That was my experience; if I ran the /RELEASE version, all went well.

The problem I encountered was specifically found to be using TRIM() in an IO list. The first PRINT ('Using 2 trim() calls)' shows that the stack pointer returns after the PRINT decremented by 16. Later on, I found that other combinations of PRINT and use of TRIM() or just specifying the length of the character string in the IO list can cause the same problem, or make the problem disappear.

Specifically, 'concat trims and print' uses three TRIM() calls, concatenating the data, but no stack problem was encountered. Also, 'trim only quad' uses TRIM() to output the first data item then outputs a full data item, and the stack is unaltered. So, in my small number of tests, it would appear that if you use TRIM() or a specified character length at the end of the IO list, then the stack pointer is badly altered.

I hope this helps to clarify.

14 Dec 2015 10:34 #17081

Bill

The problem is replicated on my machine and needs fixing so I will make a note of this.

In the meantime I suggest that you write your output to a string buffer and then use a single TRIM when PRINTing the buffer. That should allow you to continue to use /CHECKMATE.

14 Dec 2015 3:19 #17082

Paul, the problem also occurs writing to a string buffer using the WRITE(char_data,format) form as well as to a file. This was how I identified the problem initially.

Or, I may have misunderstood your response.

14 Dec 2015 5:23 #17083

OK. Can you find a way to avoid multiple calls to TRIM in an output list?

14 Dec 2015 5:51 #17084

Since this also happens even when the length of the string is specified (i.e. ABCD(1:10), or ABCD(1:I)), it becomes nightmare to recode all the formatted writes.

One interesting thing is that even though the stack is negatively affected, if I call a routine that manifests this effect, upon return, the stack is 'normal' in the calling routine. So, something is happening (and I kind of see this in the /CHECKMATE listing files I've looked at) where the stack is 'fixed' prior to return to the caller.

What I might be able to do is recode the huge, major loop in which this problem manifests itself most readily, breaking it into smaller routines that will contain the TRIM() functions and get called/fixed.

I've informed my external testers that this issue might manifest itself and have offered a 'fix'; don't process so much data, or run the /RELEASE version also supplied to them.

I have a couple of other routines that process massive amounts of data as well. These will be much more difficult to recode, but so far, they have not yet crashed due to this stack fault issue.

Thanks for pursuing the fix, Paul. I'll get by until then!

14 Dec 2015 6:07 #17085

Temporarily, I've placed code that saves the ESP register as the major loop starts and restores it before the loop end. It is certainly temporary.

This has totally eliminated the stack fault.

15 Dec 2015 8:26 #17086

Thanks. Hopefully it won't be too long before we can get this fixed.

4 May 2016 3:40 #17463

It would appear that in V8.00.0, the bug still exists, yes?

4 May 2016 5:41 #17464

Yes. Sorry about that.

4 May 2016 1:37 #17466

Paul, that's OK! I just needed to know whether or not to remove the temporary fixes I have in place.

Will look for a more permanent fix in a later release.

So far, V8.00 has been a seamless transition. Only one hiccup at link time with a STDCALL that I manually had added to a section that resulted in an undefined at link time. Inserted 'USE MSWIN' and the problem disappeared!!

Great product, and congratulations on the newest release! Bill

9 Jun 2016 10:58 #17611

This has now been fixed for the next release.

9 Jun 2016 2:06 #17614

Many thanks, Paul!!

Please login to reply.