Took me nearly 3 days to locate the error in following code:
procedure DoSomething; try something that may raise an exception except on e: EMyError1 do raise e // to re-raise the thing on e: Exception do // everything else raise EMyError2.Create('something happend'); end; end; procedure WrapperForDoSomething; begin try DoSomething; except on E: Exception do ShowMessage(e.message); DoSomethingElseWith(e); Log(e.message); end; end;
You see it, right? Yeah, me neither. Well at least I do now. I got an "Invalid Pointer Operation" right after Log(e.message). "E" was (still) accessible in the Log-Function. But was Free-ed long ago. Where do you ask? Right after the first except block in DoSomething. I didn't know this behavoir existed. It's kind of logical, now, to that this local variable in the try-except block should be destroyed afterwards.
Simple fix: instead of
... on e: EMyError1 do raise e // to re-raise the thing ...
on e: EMyError1 do
raise EMyError1.create(e.message); // to re-raise the thing in the correct way
Update Turned out that I'm wrong (or not efficient enough) on this one again. Comments & Reddit tought me the correct way:
try ... except on e: EMyError1 do raise; // to re-raise the thing in the correct way end
I'm working in a multithreaded environment and I was looking 2 of the 3 days in the wrong direction because I thought it had something to do with the (lack) of CriticalSections or Synchronization. Well - turned out to be dead simple.