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


More information about the fpc-pascal mailing list