read

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

do this: try ... except 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.

Back to Overview