yoy.be "Why-o-Why"

Good to know: don't do except on e:Exception do ... raise e;

2020-12-28 13:29  dontraisee  delphi werk  [permalink]

Good to know. At work, I inherited a smaller project. It started firing access violation errors reading from 00000000 (that tells you there's a nil pointer involved somewhere) at some address that didn't put me somewhere in the source code when I did Search > Find address in the IDE...

I was lucky I got the program running in a debugger when this happens, and the root cause was something completely different. (An SQL unique index constraint violation if you're really interested.) I got that fixed soon enough, but that didn't explain where the access violation comes from.

I followed the exception with the debugger, and before the exception was handled by anything that outputs like a logger or an error display, sure enough an access violation happend, but the debugger didn't show me anywhere else in the source code than it was already debugging, strange.

It took me a long hard look at the code before I spotted it, but with some luck you'll be able to spot what's wrong faster. The original author had the strange habit of writing exception handlers like this:

try
//important stuff here
except
on e:Exception do
begin
//stuff to do in case of an exception here, (e.g. transaction rollback)
raise e;
end;
end;

And they were all over the place. Nothing bad about that per sé, with raising the exception again, you can centralise the actual exception handling on the 'highest level' where all the calls are made. But while you're able to raise a specific exception if you create a new one*, apparently there's a difference between raise e; and raise; at least in this Delphi version I was on. Delphi handles the destruction of exception objects for you, and apparently that throws something off and causes the nil access violation somewhere deep inside...

*: Fun fact: Did you know that the Delphi runtime system creates an EOutOfMemory exception instance at the start of your programs, just to have it ready when it actually runs out of memory anytime later? Forgot where I read about that though...

twitter reddit linkedin facebook