Is it advisable to open a file in a ctor

S

subramanian100in

Is it advisable to open a file in a ctor ? Or should a file be opened
in a member function ? The reason for asking this question is the
following:
If we open the file in a ctor, then the dtor may have to close the
file. However closing a file can fail and a dtor should not perform an
operation that can fail. So a file should not be closed in a dtor but
instead it should be closed in a member function. Similarly should a
file be opened in a member function ?

Kindly explain.

Thanks
V.Subramanian
 
J

jandrm

Is it advisable to open a file in a ctor ? Or should a file be opened
in a member function ? The reason for asking this question is the
following:
If we open the file in a ctor, then the dtor may have to close the
file. However closing a file can fail and a dtor should not perform an
operation that can fail. So a file should not be closed in a dtor but
instead it should be closed in a member function. Similarly should a
file be opened in a member function ?

Kindly explain.

Thanks
V.Subramanian

Well I was about to answer.. but remembered std fstream does both..
open/close in ctor/dtor. So you can do it if you want. The question is, what
will you do in your ctor when the open fails. Change the state of some
member, or throw an exception?

Having said that, I personally would prefer to have discrete open and close
functions. And I would prefer a dtor that made a last ditch attempt to free
an OS resource like a file handle (ignoring errors).

my 2 cents :)
 
R

robertwessel2

Is it advisable to open a file in a ctor ? Or should a file be opened
in a member function ? The reason for asking this question is the
following:
If we open the file in a ctor, then the dtor may have to close the
file. However closing a file can fail and a dtor should not perform an
operation that can fail. So a file should not be closed in a dtor but
instead it should be closed in a member function. Similarly should a
file be opened in a member function ?


It's more that a dtor should never throw an exception (and even that's
not an absolute rule, but there are darn few places where doing so
makes sense - and frankly, I've never found one). What that means is
that if you close a file in a dtor (not that I think that's usually a
great idea, but...), you need to catch any exceptions from that *in*
the dtor. Which, of course, immediately brings up the question of
what to do with the fact that the close failed.
 
W

werasm

It's more that a dtor should never throw an exception (and even that's
not an absolute rule, but there are darn few places where doing so
makes sense - and frankly, I've never found one).  What that means is
that if you close a file in a dtor (not that I think that's usually a
great idea, but...), you need to catch any exceptions from that *in*
the dtor.  Which, of course, immediately brings up the question of
what to do with the fact that the close failed.

What can one do about close failing? Not much. No point throwing then.

I can imagine close failing if the descriptor is wrong, but there
is nothing you can do about it - probably crashing in those
circumstances is advisable...
 
W

werasm

Is it advisable to open a file in a ctor ?

I would think so, yes.
Or should a file be opened
in a member function ? The reason for asking this question is the
following:
If we open the file in a ctor, then the dtor may have to close the
file.

I think whether you use a constructor or an open function, the
destructor still has to close the file if it was open, not?

What if some other code throws, are you then going to leave
the file open?

RAII - wiki

Kind regards,

Werner
 
M

Miles Bader

werasm said:
What can one do about close failing? Not much. No point throwing then.

I can imagine close failing if the descriptor is wrong, but there
is nothing you can do about it - probably crashing in those
circumstances is advisable...

There are cases where a close can legimately fail, e.g. with a networked
filesystem.

One could offer a separate "close" method, which _would_ return an error
status / throw an exception, and have the destructor close the file only
if it isn't already closed (and I'd think "destructor closes" would just
ignore close failures).

Then the user can choose whether he wants to deal with close errors in
some way or not; if he doesn't really care, he can just let the
destructor doing the closing, and if he cares, can call the close
method.

-Miles
 
W

werasm

Then the user can choose whether he wants to deal with close errors in
some way or not; if he doesn't really care, he can just let the
destructor doing the closing, and if he cares, can call the close
method.

Yes, but he still has to deal with the case where an object
goes out of scope due to a potential throw. What would
you consider the best way to deal with this? What can
the user do if close fails? If he needs to do something
in the event of close failure, that can be handled by
providing some interface that [can] be accessed in
the destructor (std::cerr being and example of a
log interface).

I think as far as resources are concerned, sticking
to RAII is not a bad idea. At least close in the de-
structor.

Regards,

W
 
P

Paul N

What can one do about close failing? Not much. No point throwing then.

I can imagine close failing if the descriptor is wrong, but there
is nothing you can do about it - probably crashing in those
circumstances is advisable...

I think it would depend on whether you are reading or writing the
file. If you are reading a file, and you can't close it properly, then
the file is probably all right, the only problem is some sort of
tangle in the OS's reading mechanism that you can't do anything about
anyway. If however, you are writing data, then you probably want to
know about a failure to close correctly - you can ask the user to
delete some files and try again, or can decline to delete the previous
version of the data, etc. Try searching Google groups for "Sosman" and
"cheesegrater".

Paul.
 
J

James Kanze

Is it advisable to open a file in a ctor ? Or should a file be
opened in a member function ? The reason for asking this
question is the following:
If we open the file in a ctor, then the dtor may have to close the
file. However closing a file can fail and a dtor should not perform an
operation that can fail. So a file should not be closed in a dtor but
instead it should be closed in a member function. Similarly should a
file be opened in a member function ?

Opening a file in a constructor does *not* mean that you have to
close it in a destructor. Whether you open the file in the
constructor or in a separate function is orthogonal to whether
you close it in the destructor or not. In general:

-- If the file is essential for the constructed object to work
correctly, you should definitely consider opening it in the
constructor, and throwing an exception if the open fails.
There's no point in the object ever existing if the open
fails.

-- If the client code will have to continuously check for
errors anyway (always the case if the file is open in
input), and there's any chance of it handling an error in
opening the file immediately, you should use a separate
function, so that you can return an error code.

-- If the file is opened for reading, the client code will be
checking for errors after each read, so there's really no
problem with doing the close in the destructor.

-- If the file is opened for writing, you probably want a close
in the constructor anyway, in case of an exception, or such.
One frequent idiom in such cases is to have an explicit
close for the normal case (since the client code does need
to check for errors), but to check if the file is open in
the destructor, and if so, close it *and then delete it*.
If the file is still open in the destructor, another error
occurred, which triggered an exception, and the file is
likely not complete.
 
J

James Kanze

What can one do about close failing? Not much. No point
throwing then.
I can imagine close failing if the descriptor is wrong, but there
is nothing you can do about it - probably crashing in those
circumstances is advisable...

Close can easily fail on a file opened for writing, if, for
example, the disk is full, and the ofstream can't flush the data
to it. It's almost always necessary to check the status after
the close: if nothing else, you absolutely must notify the user
(who otherwise will think his data is correct); it's often a
good idea to delete the file with the incomplete data as well;
and of course, the application should return an error code to
the system if it's an application which terminates.

Which doesn't mean that you shouldn't also use close in the
destructor, for cleaning up in case of an error.
 
S

Stefan Ram

Daniel T. said:
are callable without throwing (an "isValid()" function.) But then you
are in the unenviable situation of having to break "tell don't ask,"

You can write this in a tell-don't-ask-style (in pseudo-code - I
have not learned the proper C++ lambda syntax yet).

outfile f( "/tmp/example" );
f.run([ &f ](){ f.write( "hello" ); f.close(); });

I used the hypothetical member function »run«, which will execute
the argument code block iff f.isValid(). Thus, we /told/ it to do
this, we did not ask it for any information.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,262
Messages
2,571,056
Members
48,769
Latest member
Clifft

Latest Threads

Top