itsols
itsols

Reputation: 5582

Lazarus (FreePascal): How do I capture a system error and throw an exception?

I am trying to show an array of TPANELs to be used by the user as a menu system. It all seems to work fine but here's the issue.

If I always click the first item (i.e., TPanel), then I can click the other items as well. But if I start by clicking the last item, it shows the error "Access violation" AFTER it has shown the items.

The strange thing is that despite the error, the system does not crash. So I enabled the debugger (DBG). Now it crashes with the error as follows: enter image description here

And once the program stops, I see the following in the history window of the debugger. enter image description here

Please note that I'm not keen right now in fixing this error as I think this is trivial. But I want to be able to capture the error as it occurs and do something (for now I want to ignore it).

I'm using Ubuntu 12.04 with Lazarus 1.0.10. The method I use must work on WINDOWS and LINUX.

Thanks in advance for any help!

Upvotes: 2

Views: 9249

Answers (2)

itsols
itsols

Reputation: 5582

First, a big thank you to TLama for all the explanations and directions. I have to accept his answer as I've built mine based on that. I'm only posting this as an answer so that another person who's a beginner to Lazarus may find this useful. I'm not in anyway suggesting that this is the best thing to do, but this is what I want to do for now. That is, when a certain exception occurs, I want to trap it and deal with it.

Given that,

  1. I am dynamically creating a set of TPanels to look like buttons
  2. Each TPanel has assigned to it a mouseclick event

Let's assume that there are 10 such 'buttons' (actually TPanels).

The problem: When I first click on the first button, I can then click on another one (eg: the 5th). But if I first click the 5th or anything else other than the first, the program throws the 'Access violation' error. Note however, that the program doe not crash despite the ugly warning about data corruption and stuff. So the user can simply click ok and continue. Strangely then, with subsequent clicks, this problem reduces! I know that's funny.

Now, as explained by TLama, the error occurs when the mouse is being released AFTER clicking a button.

But here's my problem... I don't have a mouseup event. That's part of Pascal.

So now, I want to ignore the mouseup event (at least for now). There MUST be a better way.

But there's another issue. I cannot ignore what I don't have! And I don't have a mouseup event. So I finally decided to capture this error at application level like this:

On the main form, I put this code:

procedure TfrmMainForm.CatchErr(Sender: TObject; e:exception);
begin
  if e.Message <> 'Access violation' then ShowMessage('MOL: ' + e.Message);
end; 

And then on form create, I put this:

Application.OnException:=@CatchErr;

And (for now) I can circumvent this issue.

Once again, as TLama has indicated, this is not good advice. Nonetheless, it is what I wanted to do.

Also what makes it harder is that the error is occuring in mouseup, which is in control.inc. And this is not my file. Rather it's part of Lazarus. I think it would be better if we had a way of telling Lazarus to delete that event for the TPanels in the code. I think it involves re-writing a derived class for it and I don't see how that's any good for me right now :)

Thanks again TLama!

Upvotes: 2

TLama
TLama

Reputation: 76693

Generally, to catch an exception, there's the try..except block. For sure your goal is not to catch an exception and ignore it, but find it in your code and fix the source of the problem. Of course, there might be situations, where the risk of an exception is high or expected so the use of a try..except block is necessary there. Those blocks of code we are enclosing this way:

procedure TForm1.Button1Click(Sender: TObject);
var
  NotExistingPanel: TPanel;
begin
  try
    NotExistingPanel.Caption := ''; // <- this will raise an access violation
  except
    on E: Exception do
      ShowMessage('An exception was raised: ' + E.Message);
  end;
end;

Your problem will be somewhere in an OnMouseUp event handler of some of your controls and it's been caused by accessing the memory, that the CPU cannot physically address. This might happen e.g. when you access an object which has not been created, or already released, but there are also many different ways how to cause an access violation.

Upvotes: 4

Related Questions