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)
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
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
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
@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.
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.
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
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