|
Post by Walt Decker on Apr 14, 2021 12:55:30 GMT -5
Mr. Gundel;
I will try. Bear in mind that this pertains mostly to debugging operations and that there are some user errors over which the programmer has little control other that informing the user that an error has occured (usually file errors of some type).
As you know, when an error occurs LB looks for an error trap to handle it and if it does not find one the it continues looking until it finds one. If it does not find an error trap it issues, most times, an ambiguous statement and crashes.
In the app I am currently working on I had one error trap that was activated both during startup and compleation. This was in a subroutine that cleaned up temporary files generated by and used by the app. The cleanup routine is still there but everything is done outside of LB.
When the LOADBMP error occured LB found the error trap and promptly crashed with a final message something like invalid DLL handle. The only way I was able to find the error was to write an error trap in the DLL function I was using and turn off error handling when complete.
In the DOS days of BASIC programming there was, and some BASICs still implement it, the statement "ON ERROR GOTO 0"(zero). That cleared the error flag and essentially disabled error traps until the next error occured. If the error was not trapped the app would stop and issue a statement concerning the type of error and where it occurred. If something like that could be implemented or better yet make errors local to the module in which they occur it would be a tremendous help in debugging. Having a little more comprehensive set of error codes would also be advantageous, e. g. BMP FORMAT NOT SUPPORTED is much more informative than "index: 2787 is out of collection bounds."
|
|
|
Post by Carl Gundel on Apr 14, 2021 13:37:55 GMT -5
Mr. Gundel; I will try. Bear in mind that this pertains mostly to debugging operations and that there are some user errors over which the programmer has little control other that informing the user that an error has occured (usually file errors of some type). As you know, when an error occurs LB looks for an error trap to handle it and if it does not find one the it continues looking until it finds one. If it does not find an error trap it issues, most times, an ambiguous statement and crashes. In the app I am currently working on I had one error trap that was activated both during startup and compleation. This was in a subroutine that cleaned up temporary files generated by and used by the app. The cleanup routine is still there but everything is done outside of LB. When the LOADBMP error occured LB found the error trap and promptly crashed with a final message something like invalid DLL handle. The only way I was able to find the error was to write an error trap in the DLL function I was using and turn off error handling when complete. In the DOS days of BASIC programming there was, and some BASICs still implement it, the statement "ON ERROR GOTO 0"(zero). That cleared the error flag and essentially disabled error traps until the next error occured. If the error was not trapped the app would stop and issue a statement concerning the type of error and where it occurred. If something like that could be implemented or better yet make errors local to the module in which they occur it would be a tremendous help in debugging. Having a little more comprehensive set of error codes would also be advantageous, e. g. BMP FORMAT NOT SUPPORTED is much more informative than "index: 2787 is out of collection bounds." Thank you. I will work hard to improve the error handling experience for LB5, but I am not planning to have another LB4 release.
|
|
|
Post by Walt Decker on Apr 14, 2021 14:47:54 GMT -5
"but I am not planning to have another LB4 release."
I know. That is why I mentioned it concerning LB5.
On a slightly different note concerning LB5, I hope you have implemented a data type float and the ability to pass arrays by reference to dlls.
|
|
|
Post by Carl Gundel on Apr 14, 2021 16:06:05 GMT -5
"but I am not planning to have another LB4 release." I know. That is why I mentioned it concerning LB5. On a slightly different note concerning LB5, I hope you have implemented a data type float and the ability to pass arrays by reference to dlls. The C calling features are definitely improving, but I'm hesitant to be more specific yet.
|
|
|
Post by Brandon Parker on Apr 14, 2021 19:45:23 GMT -5
Walt, You should be able to trap errors in LB4.xx reliably by placing error handling within Subroutines/Functions. This will allow the scoping of the Subroutine/Function where the error occurs to contain the error and allow it to be handled accordingly instead of just blowing back up through the stack to the topmost code and/or error handler. Of course, there are some errors which will simply crash the Runtime Engine and there is not really much one can do about those.
{:0)
Brandon Parker
|
|
|
Post by Walt Decker on Apr 15, 2021 8:19:50 GMT -5
That is true, Mr. Parker, but why put an error trap in every module, especially when an LB function is successfully used in all of them?
|
|
|
Post by Brandon Parker on Apr 15, 2021 20:50:48 GMT -5
Maybe I am not understanding what you are referring to as a module...? Can you give me a better idea of the type of error trapping you are trying to achieve, but are not able to?
Given the chance, one should always try to catch & handle errors at the lowest point possible.
{:0)
Brandon Parker
|
|
|
Post by Walt Decker on Apr 19, 2021 10:21:31 GMT -5
Mr. Parker;
To me a module is a section of code that is completely isolated from all other code. It has its own variable names, arrays, and structures and has no knowledge of anything outside itself other than global data defined outside of any runtime code. In C and some other languages they are called functions, in some langues they are called methods, and in BASIC they are called functions and subs.
I think the best way to describe the problem is through example. This is not compileable in LB.
SUB Begin
LOCAL Drvs() AS STRING
LOCAL A, _ B, _ R AS LONG
A = 1 B = 0
FN_GetDrives(Drvs$())
R = FN_DivYbyX(A, B) END SUB
'------------------------------------------ '------------------------------------------
FUNCTION FN_GetDrives(Drives() AS STRING) 'this function will produce an error
'the error trap/handler is 'not what I normally use. 'I normally use a TRY-END TRY 'BLOCK of the form 'TRY ' ... code 'CATCH ' handle the error 'END TRY
LOCAL Cdrv, _ A AS STRING
LOCAL DrvCnt, _ I AS LONG
Cdrv$ = CURDIR$
FOR I = ASC("A") TO ASC("Z") A$ = CHR$(I) ON ERROR GOTO DRV_ERROR 'if an error 'jump to handler CHDRIVE A$ DrvCnt = DrvCnt + 1 REDIM PRESERVE Drives$(1 TO DrvCnt) Drives$(DrvCnt) = A$ + ":"
ITERATE FOR 'increment I and get next 'item DRV_ERROR: ' an error occured ERR = 0 ' clear the error NEXT I
CHDIR Cdrv$
ON ERROR GOTO 0 '(label zero) close error traps 'this is not possible in LB END FUNCTION
'------------------------ '------------------------
FUNCTION FN_DivYbyX(BYVAL Y AS LONG, BYVAL X AS LONG)
'this might error depending on the X value
LOCAL Result AS LONG
Result = Y \ X 'integer divide
FN_DivYbyX = Result END FUNCTION
In the other languages I use the "ON ERROR GOTO 0" is not necessary because errors are local to the module in which they occur. In LB that statement is not possible. When a divide by zero error occurs in function FN_DivYbyX() LB will devolve to function FN_GetDrives() and lock up.
|
|
|
Post by Brandon Parker on Apr 20, 2021 22:17:12 GMT -5
Ok, but you should not need to "On Error GoTo 0" ... When you exit a Subroutine/Function the scope for any Error Trapping within the Subroutine/Function is dismissed.
As long as an error is captured within a Subroutine/Function, the program will continue as normal after departing the error handler notwithstanding any data issues the error may have caused. If you have an error occur, you can change whatever data you need to in order to prevent the error within the Error Handler and then issue the "Resume" command which will send the program flow back to the offending line that caused the error in the first place. If you handled the error correctly, the program will continue on as normal.
I have used this type of setup to do exactly what I described above inside the testFunction() function. I think this is what you are describing ...?
If you want to clear the "Err" and "Err$" variables that LB automatically fills then simply set "Err" to something that does not represent a known error code (maybe -1 or something) and set "Err$" to "" (Empty String).
Call testSubroutine 0 Call testSubroutine 2
Print testFunction(0) Print testFunction(2) End
Function testFunction(x) On Error GoTo [Error] testFunction = (1/ x) Exit Function [Error] 'Use a Select Case to check/handle 'individual errors Select Case Err Case 11 'Division by Zero Error 'Make x = 1 to be able to 'Resume without error (just for example purposes) x = 1 Resume Case Else Print Err;" : ";Err$ End Select End Function
Sub testSubroutine x On Error GoTo [Error] Print (1/ x) Exit Sub [Error] Print Err;" : ";Err$ End Sub
{:0)
Brandon Parker
|
|
|
Post by Carl Gundel on Apr 20, 2021 22:48:34 GMT -5
I'm not sure why it is necessary to clear these. If you check them in your error handler code (which should only ever be called as the result of an error condition), then they will contain the latest error values, so why clear them?
|
|
|
Post by Brandon Parker on Apr 21, 2021 8:17:41 GMT -5
Yup, I would have no need to do that, but I was just proposing it in case he wanted to be checking the values in some bizarre situation. I'm not sure what that situation might be, but ... options ...
{:0)
Brandon Parker
|
|