Calling ProcedureReturn from within a loop. More information needed in docs to clarify if this is a valid thing to do.

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
Axeman
User
User
Posts: 89
Joined: Mon Nov 03, 2003 5:34 am

Calling ProcedureReturn from within a loop. More information needed in docs to clarify if this is a valid thing to do.

Post by Axeman »

Something I always find myself scratching my head over is whether or not it is valid to use ProcedureReturn from inside a loop. It's extremely useful to be able to do this as loops are often needed when detecting abort conditions for a procedure, and using flag variables to trigger a ProcedureReturn adds extra code and complexity.

My concern is that using ProcedureReturn in that case will leave cruft behind due to loop initialization data, etc, not being cleaned up. So, ideally the documentation should be perfectly clear on whether or not using ProcedureReturn from within a loop is valid.

The current docs say:-
A call of ProcedureReturn exits immediately the procedure, even when its called inside a loop.
Which tells me nothing about whether or not it is a valid thing to do. Assuming calling it within a loop is valid then I'd rather it say:-
A call to ProcedureReturn immediately exits the procedure, even when it's called inside a loop. Note that calling ProcedureReturn from within a loop is valid, as all resources are cleaned up and no issues can arise from this approach.
Assuming calling it within a loop is not valid then I'd rather it say:-
A call to ProcedureReturn immediately exits the procedure, even when it's called inside a loop. Note that calling ProcedureReturn from within a loop is NOT valid, as some resources are not properly cleaned up and issues can arise from this approach.
Because I'm unsure which approach is valid I find myself using code such as that below.

Code: Select all

; Ensure that the nodes do not have an existing straight connection between them.
abort = 0
ForEach StraightPathList()
	If ( *node1 = StraightPathList()\node1 And *node2 = StraightPathList()\node2 ) Or ( *node2 = StraightPathList()\node1 And *node1 = StraightPathList()\node2 ) ; If the nodes are connected in either order.
		abort = 1 ; Flag that the function should abort and return a zero to indicate that the nodes can't connect.
		Break
	EndIf
Next
If abort : ProcedureReturn 0 : EndIf
User avatar
jacdelad
Addict
Addict
Posts: 1431
Joined: Wed Feb 03, 2021 12:46 pm
Location: Planet Riesa
Contact:

Re: Calling ProcedureReturn from within a loop. More information needed in docs to clarify if this is a valid thing to d

Post by jacdelad »

You can leave every loop (for, while, repeat...) and if/select structure safely. You only have to be careful when using gosub/goto within these (I, for one, have never used goto/gosub).
PureBasic 6.04/XProfan X4a/Embarcadero RAD Studio 11/Perl 5.2/Python 3.10
Windows 11/Ryzen 5800X/32GB RAM/Radeon 7770 OC/3TB SSD/11TB HDD
Synology DS1821+/36GB RAM/130TB
Synology DS920+/20GB RAM/54TB
Synology DS916+ii/8GB RAM/12TB
juergenkulow
Enthusiast
Enthusiast
Posts: 544
Joined: Wed Sep 25, 2019 10:18 am

Re: Calling ProcedureReturn from within a loop. More information needed in docs to clarify if this is a valid thing to d

Post by juergenkulow »

Code: Select all

; ProcedureReturn with CBackend Compilers\pbcompilerc.exe /Commented
Global *p
Procedure Test()          ; static integer f_test() { integer r=0; integer v_i=0;
  Shared *p               ; 
  Protected i=1           ;   v_i=1;
  While i<100             ;   while (1) { If (!(v_i<100)) { Break; }
    *p=AllocateMemory(42) ;     integer rr0=PB_AllocateMemory(42); p_p=(void*)rr0;
    Debug i               ;
    If i=13               ;     if (!(v_i==13)) { goto no3; }
      ProcedureReturn     ;       r=0; Goto end; //------------------------------------------------
    EndIf                 ;     no3:;                                                          // |
    i+1                   ;     v_i=(v_i+1);                                                   // |
    FreeMemory(*p)        ;     integer p0=(integer)p_p; integer rr1=PB_FreeMemory(p0);        // |
    *p=0                  ;     p_p=0;                                                         // |
  Wend                    ;     } il_wend1:;                                                   // |
EndProcedure              ;   end: Return r; }   //<-- ProcedureReturn jumps to the label end. ----

Test()                    ; integer rr0=f_test();
Debug Hex(*p)             ; 44012F0 // Memory leak 
User avatar
mk-soft
Always Here
Always Here
Posts: 5335
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Calling ProcedureReturn from within a loop. More information needed in docs to clarify if this is a valid thing to d

Post by mk-soft »

The resources of a procedure are deleted. Also with a ProcedureReturn, because it jumps to the "end".
// Procedure foo()
static integer f_foo() {
integer r=0;
integer v_i=0;
void* v_s1=0;
pb_list t_s2={0};
// Protected s1.s = "Hello", i
SYS_FastAllocateStringFree4(&v_s1,_S1);;
// Protected NewList s2.s()
PB_NewList(8,&t_s2,ms_s,8);;
//
// AddElement(s2())
void* p0=(void*)(t_s2.a);
integer rr0=PB_AddElement(p0);
// s2() = s1
SYS_PushStringBasePosition();
SYS_CopyString(v_s1);
SYS_AllocateString4(&(*(void**)&t_s2.b->c),SYS_PopStringBasePosition());
//
// For i = 1 To 10
v_i=1;
while(1) {
if (!((integer)10>=v_i)) { break; }
// If i = 3
if (!(v_i==3)) { goto no4; }
// ProcedureReturn
r=0;
goto end;
// EndIf
no4:;
// Next
next1:
v_i+=1;
}
il_next2:;
//
// Debug s2()
//
// EndProcedure
end:
SYS_FreeString(v_s1);
PB_FreeList(t_s2.a);
return r;
}
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Axeman
User
User
Posts: 89
Joined: Mon Nov 03, 2003 5:34 am

Re: Calling ProcedureReturn from within a loop. More information needed in docs to clarify if this is a valid thing to d

Post by Axeman »

It's good to know that it is a valid thing to do that won't lead to complications, so thanks for the info.

That fact needs to be made clear in the docs, though. That way, new Purebasic users who don't have experience with programming best practices aren't left in any doubt on the matter.
User avatar
jacdelad
Addict
Addict
Posts: 1431
Joined: Wed Feb 03, 2021 12:46 pm
Location: Planet Riesa
Contact:

Re: Calling ProcedureReturn from within a loop. More information needed in docs to clarify if this is a valid thing to d

Post by jacdelad »

The help tells it for loops, but I agree for the rest. A clear sentence would surely help.
PureBasic 6.04/XProfan X4a/Embarcadero RAD Studio 11/Perl 5.2/Python 3.10
Windows 11/Ryzen 5800X/32GB RAM/Radeon 7770 OC/3TB SSD/11TB HDD
Synology DS1821+/36GB RAM/130TB
Synology DS920+/20GB RAM/54TB
Synology DS916+ii/8GB RAM/12TB
User avatar
mk-soft
Always Here
Always Here
Posts: 5335
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Calling ProcedureReturn from within a loop. More information needed in docs to clarify if this is a valid thing to d

Post by mk-soft »

But remember that resources you have created yourself must also be released again.
This applies to AllocateMemory, AllocateStructure, dynamic objects with PB_Any (CreateImage, etc).
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Post Reply