[fpc-pascal] Re: Fpc Access Violation if AppConfigDir doesn't exist.
Giuliano Colla
giuliano.colla at fastwebnet.it
Mon Feb 11 12:29:25 CET 2013
Il 11/02/2013 09:21, Michael Van Canneyt ha scritto:
>
>
> On Mon, 11 Feb 2013, Giuliano Colla wrote:
>
>> 3) But if also the *path* to the file doesn't yet exist, it just
>> crashes without rising an exception that the user application can
>> handle somehow.
>
> This is incorrect. It does tell you why it fails.
>
>>
>> This is rather unpleasant, because the path provided by
>> GetAppConfigXx does usually exist, so you have an application which
>> 99% of the times works just fine, and 1% of the times crashes without
>> telling why.
>
> It tells you *exactly* why it 'crashes':
>
> home: >./ti
> An unhandled exception occurred at $000000000042AE87:
> EFCreateError: Unable to create file "/tmp/path/to/nothing.txt"
> $000000000042AE87
>
This is true only if you invoke the program from command line, which is
something the end user will never do. Consider that this sort of errors
doesn't pop up when you're developing, but rather after you've deployed
your application.
Let's assume that saving configuration is on a FormClose procedure, as
usual, and you have a try..finally construct, as usual.
Your user starts the program by clicking on a launching Icon.
When he clicks on a Close button, if the path doesn't exist the program
won't be terminated, and he's left with a window he can't close. On a
terminal you can see
TApplication.HandleException Unable to create file "/home/colla/.pippo/uclc.cfg"
Stack trace:
$080BAF29
[..]
exception at 080BAF29:
Unable to create file "/home/colla/.pippo/uclc.cfg".
But no error is shown on the screen (try..finally has trapped it), and
the form is not closed. Then the user will attempt to click again on the
close button of a form which is already "almost" closed. On a terminal
you can see:
TApplication.HandleException Access violation
Stack trace:
[..]
$082A9B6D GTK2WSBUTTON_CLICKED, line 2417
But again nothing on the screen. The program hangs here. From command
line you need a ^C to terminate. Otherwise you need a killall. Which
isn't a very good situation for an end user.
> home: >cat ti.pp
> program ti;
>
> uses inifiles;
>
> begin
> with TMemIniFile.create('/tmp/path/to/nothing.txt') do
> try
> WriteString('A','B','C');
> UpdateFile;
> finally
> Free;
> end;
> end.
>
> However, I agree that it should try to create the path as well.
> I have adapted the implementation.
>
> You'll get an error telling you if it failed to create the dir:
> An unhandled exception occurred at $0000000000427F7E:
> EInOutError: Could not create directory "/my/path/to/"
> $0000000000427F7E
>
> Which means that you are still (as previously) responsible for
> catching possible errors.
> But these errors should be less frequent with this change.
>
Thank you, attempting to create the path is a welcome improvement. It
makes TIniFile behavior much more consistent.
However, what I've learned from this episode is that while attempting to
save configuration data using TINIFile on program termination you should
never use a try..finally construct, as it's suggested everywhere, but
rather a try..except (or both). Otherwise you'll never be able to catch
possible errors.
Giuliano
More information about the fpc-pascal
mailing list