[fpc-pascal] FPCUnit test + raise E;

Marcos Douglas md at delfire.net
Tue Sep 17 17:27:17 CEST 2013


On Tue, Sep 17, 2013 at 12:18 PM, Marcos Douglas <md at delfire.net> wrote:
> On Sun, Sep 15, 2013 at 4:25 PM, Sven Barth <pascaldragon at googlemail.com> wrote:
>> On 15.09.2013 13:05, Marcos Douglas wrote:
>>>
>>> [[cut]]
>>>
>>>
>>> I tried. No makes difference.
>>> (could you explain which the difference to call "raise" using "raise E
>>> at [...]"?)
>>
>>
>> The raise-at statement allows you to raise an exception for a specific
>> address. This allows you to have e.g. a error handling procedure (to wrap a
>> more compilated generation of a exception class) but have the exception
>> address still point to the original call site. E.g.:
>>
>> === code begin ===
>>
>> procedure Error(aArg: Boolean);
>> begin
>>   if aArg then
>>     raise Exception.Create('Test')
>>   else
>>     raise Exception.Create('Test') at get_caller_addr(get_frame),
>> get_caller_frame(get_frame);
>> end;
>>
>> procedure Test1;
>> begin
>>   Error(True);
>> end;
>>
>> procedure Test2;
>> begin
>>   Error(False);
>> end;
>>
>> begin
>>   try
>>     Test1;
>>   except
>>     DumpExceptionBackTrace(Output);
>>   end;
>>   try
>>     Test2;
>>   except
>>     DumpExceptionBackTrace(Output);
>>   end;
>> end;
>>
>> === code end ===
>>
>> In case one the stack trace will contain Test1 and Error in case two the
>> stack trace will be only Test2.
>
> Ok, thanks for the explanation!
>
>
>>> I implemented -- but not up to Git yet -- some like that:
>>> procedure TghSQLHandler.DoOnException(E: Exception);
>>> var
>>>    NewEx: EghSQLError;
>>> begin
>>>    if Assigned(FOnException) then
>>>      FOnException(Self, E)
>>>    else
>>>    begin
>>>      NewEx := EghSQLError.Create(Self, E.Message);   // <<<
>>>      NewEx.InnerException := E;                                  // <<<
>>>      raise NewEx;
>>>    end;
>>> end;
>>>
>>> So, if I recreate the Exception, it works in any cases. As you see, I
>>> created a new property (InnerException) to save the original
>>> exception to know what the real Exception happened...
>>> But I think this introduces much more overhead to processing.
>>
>>
>> Can you access fields of the InnerException? Maybe it's a problem of
>> reraising an existing exception...
>
> Yes, I have access but no, this is not the problem. I had coded
> InnerException property after the problem to solve it, creating a new
> Exception but not missing the original one.
>
>
>>> In my code I have classes that inherited from TghSQLHandler. This
>>> class have the DoOnException method.
>>> So DoOnException can be call many times in override methods. Maybe the
>>> program "broke" the stack because "raise E" can be call and raise an
>>> exception; the next "level" raise another; and next call again.  :/
>>
>>
>> Could possibly be. If you could reproduce it in an as simple example as
>> possible that would help.
>
>
> !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
> In attachment.
> !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
>
>
>
>> Another thing you could try (just for testing): change your exception
>> handler procedure to a function that returns bool and use it like this:
>>
>> === code begin ===
>>
>>
>> procedure TghSQLConnector.Connect;
>> begin
>>   try
>>     FLib.Connect;
>>   except
>>     on E: Exception do
>>       if not DoOnException(E) then
>>         raise;
>>   end;
>> end;
>>
>> === code end ===
>>
>>
>> Regards,
>> Sven
>
> The only difference is the use of raise; instead raise E; right?
>
> Marcos Douglas

In project in attachment before, if you change the line 50
from:
    raise E;

to:
    raise Exception.Create(E.Message);

Will work... but is this correct?


Lazarus 1.1 r42461 FPC 2.6.2 i386-win32-win32/win64

Best regards,
Marcos Douglas

PS: Sorry for my late, Sven.



More information about the fpc-pascal mailing list