Forum - MCS Electronics

 

FAQFAQ SearchSearch RegisterRegister Log inLog in

Backing out of a nested Subroutine stacks

 
Post new topic   Reply to topic    www.mcselec.com Forum Index -> BASCOM-AVR old unsupported versions
View previous topic :: View next topic  
Author Message
snow

Bascom Member



Joined: 28 Jun 2005
Posts: 212
Location: Ashburton / Mid Canterbury / New Zealand

newzealand.gif
PostPosted: Thu May 22, 2025 2:51 am    Post subject: Backing out of a nested Subroutine stacks Reply with quote

Hi all,

I'm just looking for some advice on the best way to back out of nested subroutine stacks when an error occurs at a lower level. The goal is to ensure any local memory or variables are properly cleaned up as I exit back up the call chain.

Currently, I'm using a global flag to signal an error. When an issue occurs in a lower-level subroutine, I set the flag and use Exit Sub to return. Then, in the higher-level subroutine, I check the flag after the call and also exit if it's set—repeating this as needed up the chain.

Is this considered a good practice in BASCOM, or is there a better way to handle this kind of error exit flow?

Thanks in advance!

Code:


$sim
$regfile = "m328pbdef.dat"                                  
$crystal = 16000000                                            'Using crystal 16MHZ frequency
$hwstack = 64
$swstack = 128
$framesize = 73



'**************************
'SETUP SUBROUTINES
'**************************

Declare Sub SubStack1()
Declare Sub SubStack2()
Declare Sub SubStack3()
Declare Sub SubStack4()
Declare Sub SubStack5()

Dim Error_Flag as bit

Error_Flag=0

Do

 SubStack1
 Error_Flag=0

Loop

Sub SubStack1()

  SubStack2
  If Error_Flag=1 then Exit Sub
End Sub

Sub SubStack2()

  SubStack3
  If Error_Flag=1 then Exit Sub
End Sub

Sub SubStack3()

  SubStack4
  If Error_Flag=1 then Exit Sub

End Sub

Sub SubStack4()

  SubStack5
  If Error_Flag=1 then Exit Sub

End Sub


Sub SubStack5()

 Error_Flag=1
 If Error_Flag=1 then Exit Sub

End Sub

 


(BASCOM-AVR version : 2.0.8.5 , Latest : 2.0.8.7 )
Back to top
View user's profile
MWS

Bascom Member



Joined: 22 Aug 2009
Posts: 2330

blank.gif
PostPosted: Thu May 22, 2025 12:21 pm    Post subject: Re: Backing out of a nested Subroutine stacks Reply with quote

snow wrote:
...when an error occurs at a lower level.

Your sample code lacks any signalling or handling of an error.
Quote:
The goal is to ensure any local memory or variables are properly cleaned up as I exit back up the call chain.

The compiler considers local memory dim'd with "local" as void as soon the sub is exited where it was dim'd.
There's nothing to clean up.
Quote:
I set the flag and use Exit Sub to return.

Surely one way to do it, it depends on your requirements.
And as said, use not only a flag, instead or additional a bigger variable which holds the type of error.
Back to top
View user's profile
snow

Bascom Member



Joined: 28 Jun 2005
Posts: 212
Location: Ashburton / Mid Canterbury / New Zealand

newzealand.gif
PostPosted: Thu May 22, 2025 10:06 pm    Post subject: Reply with quote

Hi
Thanks MWS for your reply.

Quote:
Your sample code lacks any signalling or handling of an error.

This was just a quick example for program flow I was looking at using. The error is processed inside the sub before the flag is set and the exit sub is called

Quote:
The compiler considers local memory dim'd with "local" as void as soon the sub is exited where it was dim'd.
There's nothing to clean up.

Good to know, thanks. I was considering using a Goto instruction to jump to an entry point outside the sub, instead of using Exit Sub, but I wasn’t sure how that would affect the Local variables. Specifically, I was wondering whether they’re still discarded properly when exiting the sub via Goto, or if that behaves differently compared to a normal Exit Sub.

Quote:
instead or additional a bigger variable which holds the type of error.

Yes, I'm using a larger variable to store multiple error flags, and then masking the relevant bits to handle specific errors as needed. It's working well for tracking multiple conditions in one go
Back to top
View user's profile
MWS

Bascom Member



Joined: 22 Aug 2009
Posts: 2330

blank.gif
PostPosted: Fri May 23, 2025 5:50 am    Post subject: Reply with quote

snow wrote:
...using a Goto instruction to jump to an entry point outside the sub, instead of using Exit Sub...

Uh, that would be quite a foul.
First, as a sub is called, the caller address is pushed on HW-stack, without regulary exit it stays there, clogging up the stack space and finally resulting in stack overflow.
Next, if these subs in later, actual code use any parameters, the registers YL:YH, which serve as SW-stack pointer, are set up, but without proper cleanup if the sub does not return properly. Again with the option of stack overflow, this time the SW-stack.

By jumping ouside the frame of a sub or function, you'd break basic rules.
A call outside to another sub with following proper return is no problem, a jump = Goto is.

Is your code's error handling that urgent, that you think about such methods?
Back to top
View user's profile
snow

Bascom Member



Joined: 28 Jun 2005
Posts: 212
Location: Ashburton / Mid Canterbury / New Zealand

newzealand.gif
PostPosted: Fri May 23, 2025 1:10 pm    Post subject: Reply with quote

Quote:
Uh, that would be quite a foul.

Yes, I figured there’d be stack issues if I just used a Goto to jump back to a base subroutine. But was worth asking for advice. Definitely seems best to unwind the subroutine calls properly and check for any error flags as you go. Keeps things clean and avoids unexpected behavior.
Quote:
Is your code's error handling that urgent, that you think about such methods?

My code is running stepper motors, and part of the process includes ray casting calculations to determine whether a point is inside or outside a polygon. There’s also UART data and other tasks that need attention once the ray casting is done. Rather than trying to jump around in the subs, I just set flags during the calculations and handle housekeeping tasks afterward in a controlled manner. Keeps the flow manageable and avoids potential stack or state issues.
Back to top
View user's profile
albertsm

Administrator



Joined: 09 Apr 2004
Posts: 6180
Location: Holland

blank.gif
PostPosted: Fri May 23, 2025 1:37 pm    Post subject: Reply with quote

While some clever code could be made it will make your code unreadable. And in all languages i know it will work the same.
But why not using a function? you assign a return value for the error :

do
if myFunc1()=0 then
if myFunc2()=0 then
if myFunc3(param,2,4) =0 then

etc.


and instead of exit sub you use exit function.
if any of the functions return non zero there is an error and none of the other funcs are called.

_________________
Mark
Back to top
View user's profile Visit poster's website
snow

Bascom Member



Joined: 28 Jun 2005
Posts: 212
Location: Ashburton / Mid Canterbury / New Zealand

newzealand.gif
PostPosted: Fri May 23, 2025 9:51 pm    Post subject: Reply with quote

Hi Mark
Quote:
do
if myFunc1()=0 then
if myFunc2()=0 then
if myFunc3(param,2,4) =0 then
etc.

I'm not quite sure I follow your example—could you elaborate a bit more? Are you suggesting the code should be placed at the top level only, or repeated in each subroutine?

At the moment, I’ve implemented a HouseKeeping() function that I call even from within deeper nested subs. It returns a value indicating whether a warning or critical error occurred. Since some of the tasks—like ray casting—can be quite CPU-intensive, I check the return value and, if needed, set a flag and begin backing out of the subroutine stack. I repeat this process at each level until I return to the top.

I realize there are other approaches, like using a timer ISR, but I went with this method because it's more transparent and keeps control flow easier to follow in my case, but its is not always prefect. Feed back is always appreciated
Back to top
View user's profile
albertsm

Administrator



Joined: 09 Apr 2004
Posts: 6180
Location: Holland

blank.gif
PostPosted: Sat May 24, 2025 9:19 am    Post subject: Reply with quote

yes i suggest that you put the code at the top level. And that you rewrite the sub as function.
that is based on your example.

Code:
declare function func1() as byte
declare function func2() as byte
declare function func3() as byte

do
   if func1()=0 then
      if func2()=0 then
          if func3()=0 then
             'all ok
          else
             'error
          end if
      else
         'error
      end if
   else
      'errror
   end if
loop


function func1() as byte
  func1=1 'assume error
  if something=ok
       if otherthing =ok then
         func1=0 'all ok
       end if
  end if
end function

'or do this
function func2() as byte
   func2=0 'assume all ok
   if errorOccured then
      func2=10 : exit function
  end if
end function
 

etc.

this will clean up local vars when used.
NEVER jump out of a function or sub unless there are no local vars and no parameters passed.

other options are possible but then you would need to show some example that uses goto. and it must be a real good representation of what you want.

_________________
Mark
Back to top
View user's profile Visit poster's website
snow

Bascom Member



Joined: 28 Jun 2005
Posts: 212
Location: Ashburton / Mid Canterbury / New Zealand

newzealand.gif
PostPosted: Tue May 27, 2025 8:20 am    Post subject: Reply with quote

Thanks Mark for your feedback.
Your foresight is truly appreciated.

Cheers
Snow
Back to top
View user's profile
Display posts from previous:   
Post new topic   Reply to topic    www.mcselec.com Forum Index -> BASCOM-AVR old unsupported versions All times are GMT + 1 Hour
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You cannot download files in this forum