View previous topic :: View next topic |
Author |
Message |
snow
Joined: 28 Jun 2005 Posts: 212 Location: Ashburton / Mid Canterbury / New Zealand

|
Posted: Thu May 22, 2025 2:51 am Post subject: Backing out of a nested Subroutine stacks |
|
|
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 |
|
 |
MWS
Joined: 22 Aug 2009 Posts: 2330

|
Posted: Thu May 22, 2025 12:21 pm Post subject: Re: Backing out of a nested Subroutine stacks |
|
|
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 |
|
 |
snow
Joined: 28 Jun 2005 Posts: 212 Location: Ashburton / Mid Canterbury / New Zealand

|
Posted: Thu May 22, 2025 10:06 pm Post subject: |
|
|
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 |
|
 |
MWS
Joined: 22 Aug 2009 Posts: 2330

|
Posted: Fri May 23, 2025 5:50 am Post subject: |
|
|
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 |
|
 |
snow
Joined: 28 Jun 2005 Posts: 212 Location: Ashburton / Mid Canterbury / New Zealand

|
Posted: Fri May 23, 2025 1:10 pm Post subject: |
|
|
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 |
|
 |
albertsm
Joined: 09 Apr 2004 Posts: 6180 Location: Holland

|
Posted: Fri May 23, 2025 1:37 pm Post subject: |
|
|
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 |
|
 |
snow
Joined: 28 Jun 2005 Posts: 212 Location: Ashburton / Mid Canterbury / New Zealand

|
Posted: Fri May 23, 2025 9:51 pm Post subject: |
|
|
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 |
|
 |
albertsm
Joined: 09 Apr 2004 Posts: 6180 Location: Holland

|
Posted: Sat May 24, 2025 9:19 am Post subject: |
|
|
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 |
|
 |
snow
Joined: 28 Jun 2005 Posts: 212 Location: Ashburton / Mid Canterbury / New Zealand

|
Posted: Tue May 27, 2025 8:20 am Post subject: |
|
|
Thanks Mark for your feedback.
Your foresight is truly appreciated.
Cheers
Snow |
|
Back to top |
|
 |
|