[Win32] Exception handling using Try/Catch/Finally

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
stephaneweg
Posts: 3
Joined: Oct 20, 2016 17:55

Re: [Win32] Exception handling using Try/Catch/Finally

Post by stephaneweg »

I just made a platform independant try catch mechanism for freebasic:



trycatch.bi

Code: Select all

type TryContext field=1
    Esp as unsigned integer
    Eip as unsigned integer
    Ebp as unsigned integer
end type

type Exception field=1
    TypeName as unsigned byte ptr
    Message as string
    Code as unsigned integer
    ObjData as any ptr
end type

dim shared ExceptionTypeName as unsigned byte ptr=@"Exception"
dim shared nbrTry as unsigned integer=0
dim shared Trys(0 to 255) as TryContext
declare function TRY() as Exception ptr
declare sub THROW(code as unsigned integer, msg as string,objData as any ptr)

#define BeginTry   do: var ex=Try(): select case ex: case 0:
#define Catch(v) nbrTry-=1: case else: var v=ex:
#define EndTry end select: loop while(0)
trycatch.bas

Code: Select all

function TRY() as Exception ptr
    dim _esp as unsigned integer
    dim _eip as unsigned integer
    dim _ebp as unsigned integer
    'saving the pointers (eip, ebp, and esp) to our table
    asm    
        push [ebp+4]
        pop [_eip]
        push [ebp+0]
        pop [_ebp]
        mov [_esp],ebp
    end asm
    Trys(nbrTry).esp=_esp
    Trys(nbrTry).ebp=_ebp
    Trys(nbrTry).eip=_eip
    nbrTry+=1
'return 0 for the select case statement
    return 0
end function

sub THROW(errno as unsigned integer, msg as string,objData as any ptr)
    dim _esp as unsigned integer
    dim _eip as unsigned integer
    dim _ebp as unsigned integer
    if (nbrTry=0) then return
    nbrTry-=1
    'retrieving the pointers
    _esp=Trys(nbrTry).esp
    _eip=Trys(nbrTry).eip
    _ebp=Trys(nbrTry).ebp
    'creating an exception object
    var newException=cptr(Exception ptr,allocate(sizeof(EXCEPTION)))
    newException->TypeName=ExceptionTypeName
    newException->Code=errno
    newException->Message=msg
    newException->ObjData=objData
    'restoring the pointer and hte eip
    asm
        mov eax,[_esp]
        push [_eip]
        pop [eax+4]
        push [_ebp]
        pop [eax]
        mov esp,eax
        'put the exception object pointer to eax as return value
        mov eax,[newException]
        pop ebp
        'now the stack is as before the try... statement, in the select case, the value will be different from zero, so it will run the case else
        ret 
    end asm
    
    return
end sub
main.bas

Code: Select all

declare sub mySub()

BeginTry
    print "this is inside my try"
    mySub()
    print "if all is ok"
Catch(myException)
    if (myException->TypeName=ExceptionTypeName) then
        print "an exception occured"
        print myException->Message
    else
        print "unknow exception occured"
    end if
EndTry
sleep

sub mySub()
    print "im inside my sub"
    THROW(1,"this is an exception from my sub",0)
    print "this should not be shown"
end sub
Tourist Trap
Posts: 2958
Joined: Jun 02, 2015 16:24

Re: [Win32] Exception handling using Try/Catch/Finally

Post by Tourist Trap »

Cherry wrote:I wonder why nobody is interested in this.
It's very interesting! Just gone unseen with the time!
htm_hx
Posts: 17
Joined: May 24, 2017 19:42

Re: [Win32] Exception handling using Try/Catch/Finally

Post by htm_hx »

FB can produce a stable try like VC exception mechanism; the landlord's code, I tested the DLL injection into the process to throw an exception, the process disappeared directly
Cherry
Posts: 358
Joined: Oct 23, 2007 12:06
Location: Austria
Contact:

Re: [Win32] Exception handling using Try/Catch/Finally

Post by Cherry »

@stephaneweg It's cool but please be aware that this doesn't actually catch exceptions, only those custom things you throw in a custom way. Try accessing bad memory for example, or on Windows call `RaiseException`, and your program will still crash. It won't catch system exceptions.
PeterHu
Posts: 148
Joined: Jul 24, 2022 4:57

Re: [Win32] Exception handling using Try/Catch/Finally

Post by PeterHu »

Cherry wrote: Oct 19, 2023 7:58 @stephaneweg It's cool but please be aware that this doesn't actually catch exceptions, only those custom things you throw in a custom way. Try accessing bad memory for example, or on Windows call `RaiseException`, and your program will still crash. It won't catch system exceptions.
May I know is there a updated version workable for 64 bit? Just tried ,built successfully for 32 bit but failed to compile for 64 bit FBC.
adeyblue
Posts: 299
Joined: Nov 07, 2019 20:08

Re: [Win32] Exception handling using Try/Catch/Finally

Post by adeyblue »

64-bit Windows exceptions work differently. It'd need a bit of rewriting rather than just tweaks.

Once upon a time I added Windows & Linux/GCC native exception handling to the compiler so you could try/catch them with On Error. It worked but
a) I doubted any one would ever turn it on. I mean, everybody who knows freebasic has got on fine without them.
b) I've never added object unwinding before (calling the destructors for things within a Try when an exception happens) so my solution of instrumenting the code with labels and building tables hit a few snags. One the one hand, that's apparently how GCC does it for C++ unwinding on a simple level; on the other, GCCs optimiser can rearrange instruction order. Code that's part of GCC can obviously update their tables when it does that but when you're just running it like FB does, the tables start being wrong. You can tell GCC not to do that but it takes like 5 different options and makes for less optimised functions and I wasn't happy with how brittle it seemed to be.

So it's sat on a hard drive not being used, instead of in FBC not being used :D
PeterHu
Posts: 148
Joined: Jul 24, 2022 4:57

Re: [Win32] Exception handling using Try/Catch/Finally

Post by PeterHu »

adeyblue wrote: Oct 30, 2023 4:12 64-bit Windows exceptions work differently. It'd need a bit of rewriting rather than just tweaks.

Once upon a time I added Windows & Linux/GCC native exception handling to the compiler so you could try/catch them with On Error. It worked but
a) I doubted any one would ever turn it on. I mean, everybody who knows freebasic has got on fine without them.
b) I've never added object unwinding before (calling the destructors for things within a Try when an exception happens) so my solution of instrumenting the code with labels and building tables hit a few snags. One the one hand, that's apparently how GCC does it for C++ unwinding on a simple level; on the other, GCCs optimiser can rearrange instruction order. Code that's part of GCC can obviously update their tables when it does that but when you're just running it like FB does, the tables start being wrong. You can tell GCC not to do that but it takes like 5 different options and makes for less optimised functions and I wasn't happy with how brittle it seemed to be.

So it's sat on a hard drive not being used, instead of in FBC not being used :D
Thank you very much !
Post Reply