[Windows XP+] Try .. Catch .. EndTry - Error Handling

Share your advanced PureBasic knowledge/code with the community.
User avatar
Danilo
Addict
Addict
Posts: 3037
Joined: Sat Apr 26, 2003 8:26 am
Location: Planet Earth

[Windows XP+] Try .. Catch .. EndTry - Error Handling

Post by Danilo »

Simple Macros for catching program exceptions and continue the program.

Requires Windows XP or newer, 32bit and 64bit PureBasic.

Code: Select all

;---[ Try Catch EndTry ]----------------------------------------------------
;
; Structured Exception Handling for WinXP+, PureBasic/Windows 32bit + 64bit
;
; by Danilo, May 2012
;
Import "kernel32.lib"
    AddVectoredExceptionHandler(FirstHandler.l, *VectoredHandler)
    RemoveVectoredExceptionHandler(*Handler)
EndImport

Structure ExceptionHandlerStack
    catchAddress.i
    oldHandler.i
    StackPointer.i
EndStructure

Threaded NewList ExceptionHandlerList.ExceptionHandlerStack()
Threaded CurrentExceptionInfo.EXCEPTION_POINTERS

Procedure.l UnhandledExceptionFilter(*ExceptionInfo.EXCEPTION_POINTERS)

    CopyStructure(*ExceptionInfo,@CurrentExceptionInfo,EXCEPTION_POINTERS)

    CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
        *ExceptionInfo\ContextRecord\Eip = ExceptionHandlerList()\catchAddress
        *ExceptionInfo\ContextRecord\Esp = ExceptionHandlerList()\StackPointer
    CompilerElse
        *ExceptionInfo\ContextRecord\Rip = ExceptionHandlerList()\catchAddress
        *ExceptionInfo\ContextRecord\Rsp = ExceptionHandlerList()\StackPointer
    CompilerEndIf

    ;SetUnhandledExceptionFilter_( ExceptionHandlerList()\oldHandler )
    RemoveVectoredExceptionHandler( ExceptionHandlerList()\oldHandler )

    DeleteElement( ExceptionHandlerList() )
    ProcedureReturn $ffffffff

EndProcedure

Procedure AddExceptionHandler(*catch,StackPointer.i)
    If AddElement( ExceptionHandlerList() )
        ;ExceptionHandlerList()\oldHandler   = SetUnhandledExceptionFilter_(@UnhandledExceptionFilter()) ; Win2000pro+ 32bit
        ExceptionHandlerList()\oldHandler   = AddVectoredExceptionHandler(1,@UnhandledExceptionFilter()) ; XP+
        ExceptionHandlerList()\catchAddress = *catch
        ExceptionHandlerList()\StackPointer = StackPointer
    EndIf
EndProcedure

Global AddExceptionHandler.i = @AddExceptionHandler()

! macro __try {
!    local label1, label2, label3
!    handler_label equ label1
!    handler_end_label equ label2
!    end_try_label equ label3
! }

Macro Try
    CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
    !__try
    ! push esp
    ! push handler_label
    ! call [v_AddExceptionHandler]
    CompilerElse
    !__try
    ! mov qword rdx, rsp
    ! mov qword rcx, handler_label
    ! call qword [v_AddExceptionHandler]
    CompilerEndIf
EndMacro

Macro Catch
    !jmp end_try_label
    !handler_label:
EndMacro

Macro EndTry
    !end_try_label:
    ! restore handler_label
    ! restore end_try_label
    ! restore handler_end_label
EndMacro

;---------------------------------------------------------------------------

CompilerIf #PB_Compiler_Debugger
    ;CompilerError "please disable debugger"
    DisableDebugger
CompilerEndIf


Procedure a()

    Try

        Try

           a = 0
           b = 4/a ; 4/0 = division by zero exception

        Catch

           MessageRequester("INFO","Catched inner exception")

        EndTry
    
        PokeI(0,1234) ; Poke something to address 0
    
    Catch

       MessageRequester("INFO","Catched outer exception")

    EndTry

EndProcedure


Procedure b()
    !push 1234 ; change stack = crash
EndProcedure


a()


Try
    b()
Catch
    MessageRequester("INFO","Catched stack corruption")
EndTry


MessageRequester("INFO","OK, still alive ;)")
The variable "CurrentExceptionInfo" contains the exception informations.
Last edited by Danilo on Wed May 09, 2012 5:32 pm, edited 1 time in total.
dige
Addict
Addict
Posts: 1247
Joined: Wed Apr 30, 2003 8:15 am
Location: Germany
Contact:

Re: [Windows XP+] Try .. Catch .. EndTry - Error Handling

Post by dige »

Thank you Danilo. It it the same mechanism like the POSL TryCatch Lib?
"Daddy, I'll run faster, then it is not so far..."
User avatar
Danilo
Addict
Addict
Posts: 3037
Joined: Sat Apr 26, 2003 8:26 am
Location: Planet Earth

Re: [Windows XP+] Try .. Catch .. EndTry - Error Handling

Post by Danilo »

dige wrote:Thank you Danilo. It it the same mechanism like the POSL TryCatch Lib?
I don't know. Wasn't aware there was already a Try..Catch somewhere.
Little John
Addict
Addict
Posts: 4519
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: [Windows XP+] Try .. Catch .. EndTry - Error Handling

Post by Little John »

Great! Thank you, Danilo.

Regards, Little John
User avatar
skywalk
Addict
Addict
Posts: 3972
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: [Windows XP+] Try .. Catch .. EndTry - Error Handling

Post by skywalk »

Very cool Danilo, can't wait to "Try" this. :wink:
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
User avatar
Kiffi
Addict
Addict
Posts: 1353
Joined: Tue Mar 02, 2004 1:20 pm
Location: Amphibios 9

Re: [Windows XP+] Try .. Catch .. EndTry - Error Handling

Post by Kiffi »

Thanks Danilo!

Works under 32 Bit. But under 64 Bit:

Image

Did i missed something?

Greetings ... Kiffi
Hygge
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Re: [Windows XP+] Try .. Catch .. EndTry - Error Handling

Post by ts-soft »

Kiffi wrote:Did i missed something?

Greetings ... Kiffi
I think, you have enabled the Debugger :wink:
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
User avatar
Danilo
Addict
Addict
Posts: 3037
Joined: Sat Apr 26, 2003 8:26 am
Location: Planet Earth

Re: [Windows XP+] Try .. Catch .. EndTry - Error Handling

Post by Danilo »

Kiffi wrote:Thanks Danilo!

Works under 32 Bit. But under 64 Bit:

Image

Did i missed something?

Greetings ... Kiffi
I wondered about this too. I made a small mistake: First argument of AddVectoredExceptionHandler()
has to be nonzero to become the first handler. I changed it in the code above, thanks.
User avatar
Kiffi
Addict
Addict
Posts: 1353
Joined: Tue Mar 02, 2004 1:20 pm
Location: Amphibios 9

Re: [Windows XP+] Try .. Catch .. EndTry - Error Handling

Post by Kiffi »

@Danilo: Works perfect! Thanks a lot! Image

Greetings ... Kiffi
Hygge
User avatar
RichAlgeni
Addict
Addict
Posts: 914
Joined: Wed Sep 22, 2010 1:50 am
Location: Bradenton, FL

Re: [Windows XP+] Try .. Catch .. EndTry - Error Handling

Post by RichAlgeni »

Would this replace OnErrorCall()?

Coming from a background that had no Try-Catch, could you give me a quick heads up to someone would utilize this? Would it be useful in using functions over a network, where it's possible for the network connection to be dropped, and this procedure might gracefully handle that situation?

Thanks!
dige
Addict
Addict
Posts: 1247
Joined: Wed Apr 30, 2003 8:15 am
Location: Germany
Contact:

Re: [Windows XP+] Try .. Catch .. EndTry - Error Handling

Post by dige »

@Danilo: Duno why, but using try / catch for CatchImage and LoadImage, makes the program unstable...
I use the OnError Lib too. May be there are now some side effects?
"Daddy, I'll run faster, then it is not so far..."
TeraByte
User
User
Posts: 40
Joined: Wed May 09, 2012 12:40 am

Re: [Windows XP+] Try .. Catch .. EndTry - Error Handling

Post by TeraByte »

Thank you Danilo for your excellent code! :D
Little John
Addict
Addict
Posts: 4519
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: [Windows XP+] Try .. Catch .. EndTry - Error Handling

Post by Little John »

Danilo wrote:Simple Macros for catching program exceptions and continue the program.

Requires Windows XP or newer
Danilo, what happens if I use this code in a compiled EXE program, and someone runs that program on Windows 2000? OK, your code will probably not catch exceptions then ... but can it cause any problems on Windows 2000?

Regards, LIttle John
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Re: [Windows XP+] Try .. Catch .. EndTry - Error Handling

Post by ts-soft »

@Little John
If imported functions not available, so your exe will not start!

I think, dynamic load of functions should help.
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
User avatar
Danilo
Addict
Addict
Posts: 3037
Joined: Sat Apr 26, 2003 8:26 am
Location: Planet Earth

Re: [Windows XP+] Try .. Catch .. EndTry - Error Handling

Post by Danilo »

Little John wrote:Danilo, what happens if I use this code in a compiled EXE program, and someone runs that program on Windows 2000? OK, your code will probably not catch exceptions then ... but can it cause any problems on Windows 2000?

Regards, LIttle John
As ts-soft said, the exe will not start because the functions imports are not found in kernel32.lib

If you change the 2 out-commented lines, it should work with Win95+, but only with 32bit PureBasic.
First 64bit Windows was WindowsXP, right?

So for 32bit only and Win95+ use this version:

Code: Select all

;---[ Try Catch EndTry ]----------------------------------------------------
;
; Structured Exception Handling for Win95+, PureBasic/Windows 32bit only
;
; by Danilo, May 2012
;
Structure ExceptionHandlerStack
    catchAddress.i
    oldHandler.i
    StackPointer.i
EndStructure

Threaded NewList ExceptionHandlerList.ExceptionHandlerStack()
Threaded CurrentExceptionInfo.EXCEPTION_POINTERS

Procedure.l UnhandledExceptionFilter(*ExceptionInfo.EXCEPTION_POINTERS)

    CopyStructure(*ExceptionInfo,@CurrentExceptionInfo,EXCEPTION_POINTERS)

    CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
        *ExceptionInfo\ContextRecord\Eip = ExceptionHandlerList()\catchAddress
        *ExceptionInfo\ContextRecord\Esp = ExceptionHandlerList()\StackPointer
    CompilerElse
        CompilerError "This version of Try/Catch does not support 64bit PureBasic"
    CompilerEndIf

    SetUnhandledExceptionFilter_( ExceptionHandlerList()\oldHandler )

    DeleteElement( ExceptionHandlerList() )
    ProcedureReturn $ffffffff

EndProcedure

Procedure AddExceptionHandler(*catch,StackPointer.i)
    If AddElement( ExceptionHandlerList() )
        ExceptionHandlerList()\oldHandler   = SetUnhandledExceptionFilter_(@UnhandledExceptionFilter()) ; Win95+ 32bit
        ExceptionHandlerList()\catchAddress = *catch
        ExceptionHandlerList()\StackPointer = StackPointer
    EndIf
EndProcedure

Global AddExceptionHandler.i = @AddExceptionHandler()

! macro __try {
!    local label1, label2, label3
!    handler_label equ label1
!    handler_end_label equ label2
!    end_try_label equ label3
! }

Macro Try
    CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
    !__try
    ! push esp
    ! push handler_label
    ! call [v_AddExceptionHandler]
    CompilerElse
    !__try
    ! mov qword rdx, rsp
    ! mov qword rcx, handler_label
    ! call qword [v_AddExceptionHandler]
    CompilerEndIf
EndMacro

Macro Catch
    !jmp end_try_label
    !handler_label:
EndMacro

Macro EndTry
    !end_try_label:
    ! restore handler_label
    ! restore end_try_label
    ! restore handler_end_label
EndMacro

;---------------------------------------------------------------------------

CompilerIf #PB_Compiler_Debugger
    ;CompilerError "please disable debugger"
    DisableDebugger
CompilerEndIf

Procedure a()

    Try

        Try

           a = 0
           b = 4/a ; 4/0 = division by zero exception

        Catch

           MessageRequester("INFO","Catched inner exception")

        EndTry
    
        PokeI(0,1234) ; Poke something to address 0
    
    Catch

       MessageRequester("INFO","Catched outer exception")

    EndTry

EndProcedure


Procedure b()
    !push 1234 ; change stack = crash
EndProcedure


a()


Try
    b()
Catch
    MessageRequester("INFO","Catched stack corruption")
EndTry


MessageRequester("INFO","OK, still alive ;)")
dige wrote:I use the OnError Lib too. May be there are now some side effects?
Yes, I think the OnError Lib uses the same functions internally.
Post Reply