From: Keane Gonzalez on
I have this weird problem using fclose/fopen. I have a file that fopens successfully, then closes successfully, but it able to be used after it is fclosed. So it's basically something like
%--------------------------
fp1 = fopen('file1','a')
%do some fwrites to fp1
fclose(fp1)
fp2 = fopen('file2','a')
%an ftell(fp1) here gives an output of 0.
fwrite(fp1,'text') %should be fp2, but there is a typo in code that I can't alter
fclose(fp2)
%----------------------------

This code works and when I try to open something using fp1 (when the code is in debugging mode), it fails, as it should (after closing). The next code opens another file (file2) and then tries to write to it, but in this case, there is a typo and it actually attemps to write to file1 (which was closed). What is weird is that the fwrite actually goes through okay. When I do an ftell on fp1 after fp2 is opened, I get a location of 0. Before the fp2 is created, ftell fails on fp1.

I can't change the typo at the moment (no access) and the code has run for years with this typo without incident. The code has run on various flavors of LINUX matlab (6.x -7.9). Any ideas?

Thanks,


Keane Gonzalez
From: Keane Gonzalez on
I am adding a little bit more info to this. It just so happens that the file identifier for the first fopen seems to be reused every time for the fopen of the second (after the first file identifier is closed). So when the fwrite statement goes through, even though the old file identifier is used, it has the same fid as the newly opened file (which should have been written to in the first place).
For this case, it just happens that the typo works out as the file identifier for the closed file (which comes back to life after opening the second file, no clue why) is the same as the newly opened file. Matlab didn't mark this with a warning in MLINT. I can see why it works, but still can't understand why it's not at least a warning.


Keane
From: Walter Roberson on
Keane Gonzalez wrote:
> I am adding a little bit more info to this. It just so happens that the
> file identifier for the first fopen seems to be reused every time for
> the fopen of the second (after the first file identifier is closed). So
> when the fwrite statement goes through, even though the old file
> identifier is used, it has the same fid as the newly opened file (which
> should have been written to in the first place). For this case, it just
> happens that the typo works out as the file identifier for the closed
> file (which comes back to life after opening the second file, no clue
> why) is the same as the newly opened file. Matlab didn't mark this with
> a warning in MLINT. I can see why it works, but still can't understand
> why it's not at least a warning.

Ah, yes, that makes sense to me now.

The behaviour of returning the lowest "available" file number is consistent
with Unix conventions, where the behaviour has subtle but important
implications for the mechanisms for starting new processes with particular
files or programs linked to standard input, standard output, standard error,
and possibly other connections. It is the mechanism used in Unix shells to
implement the behaviour of "<" (redirect input) and ">" (redirect output) and
"|" (pipe output -- which also implies pipe input to the second process).

When you fclose() a file, the identifier you used to hold the file identifier
is not cleared. Clearing it would not, in general, provide much functionality,
considering that a file identifier can be copied through assignment or can be
passed down as an input parameter (or can be passed through a GUI mechanism),
etc..

As the file identifiers are simple integers, there is no internal difference
between

fid = fopen(FileName,'r');
fgetl(fid);

and

fid = fopen(FileName,'r');
fgetl(3);

if you _happen_ to know that the identifier would evaluate to 3.

Likewise,

nextfile = 0;
fids = zeros(length(FileNames),1);
fid = fopen(FileName,'r');
nextfile = nextfile + 1;
fids(nextfile) = fid;
fgetl(fids(nextfile));

All kinds of ways you could potentially get a numeric fid; and I'm sure you
could imagine program paths in which clearing the file identifier would be the
wrong thing to do...

fid = fopen(FileName,'r');
mydata{fid} = fread(fid);
fclose(fid);
disp(mydata{fid}); %would not be expected to crash...


You did not suggest that the fid _should_ be cleared, but short of making the
file identifier an object (which could have uses), you can see that as far as
the internal implementation is concerned, it is numeric _value_ of the fid
that is important, not the identifier name, so detecting this as an error or
warning during execution would be difficult.


I do not know how MLINT works, so I do not know how difficult it would be for
MLINT to internally mark the identifier as "sort of cleared" and given a
warning if it is reused before being re-assigned. I agree that it would be a
useful MLINT warning if MLINT can reasonably do it.