Thread: Should you manually close an fstream?

  1. #1
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853

    Should you manually close an fstream?

    I have seen both "yes" and "no" as an answer to this. Most examples would show me
    Code:
    ifstream ifs ("mytest.txt");
    //do something
    ifstream.close();
    Yet fstream has close() on its destructor (it is C++....) and if you really want to close it at a specific point it seems better to use a scope bracket as it is cleaner and less bug-prone.
    Code:
    //some code
    {
     ifstream ifs ("mytest.txt");
     //do something
    }
    //some code
    On the other hand if you don't close() it manually you cannot check the failbit and potentially miss an error. Yet, in most (if not all) examples I see there is never a check on close(). If you were to check also for failures usually you are worried of losing data. In which case maybe you prefer to call flush() and in any case you could wrap up the fstream in a class that handles the error appropriately without require manual releasing of resources.

    What is the common practice for this?

    As a note, if I search on MSDN site for file stream in Visual C++ I see example with ifstream and close(). Yet if I search for C# I see examples where the "using" schema with a stream reader is used, which does essentially what a C++ destrcutor does (apart from the memory release part)!

  2. #2
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    On the other hand if you don't close() it manually you cannot check the failbit and potentially miss an error. Yet, in most (if not all) examples I see there is never a check on close()
    Usually the check for failure would be spurious, since code is organized to follow idioms like RAII (Resource Acquisition Is Initialization). You don't need to check if you can guarantee that close() is only called on an open file.

    What is the common practice for this?
    I think destructors are being used wherever possible since that also follows RAII. The close() member is something I use( and encounter more often in other code) in situations where I'm going to be closing an open file and reopening it.

  3. #3
    Registered User
    Join Date
    May 2010
    Posts
    4,633
    There are times when you want to reuse your stream instance. It is possible to open one file, process it, close it, then open a different file for processing.

    I recommend closing your stream when you are finished with it. This can really be important with output streams since closing the stream flushes the buffer, writing the information to the file.

    If you are really worried about the stream not closing properly then you should probably be using exceptions instead of testing the stream state, after all this is an exceptional case.

    Jim

  4. #4
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    Quote Originally Posted by jimblumberg View Post
    There are times when you want to reuse your stream instance. It is possible to open one file, process it, close it, then open a different file for processing.
    Yes, but this is not the typical case you see in examples showing how to use an ifstream. The examples are usually how to read from file, not how to read multiple files with the same file handler.

  5. #5
    Registered User rogster001's Avatar
    Join Date
    Aug 2006
    Location
    Liverpool UK
    Posts
    1,472
    I have read other members dismissing the use of close - as once out of scope the destructor will be called anyway , or the argument went something like that anyhow. However, one i agree with whiteflags, reuse situations are obviously one for programmer calling close - but two i think that a programmer should take responsibility for closing streams, tidying memory or whatever (providing that functionality is exposed of course) I really dont like things like garbage collection or auto initilisation, I just dont like thinking 'oh thats ok, its guaranteed to be null or 0 or "" or whatever' Would rather spend the extra code lines myself.
    Thought for the day:
    "Are you sure your sanity chip is fully screwed in sir?" (Kryten)
    FLTK: "The most fun you can have with your clothes on."

    Stroustrup:
    "If I had thought of it and had some marketing sense every computer and just about any gadget would have had a little 'C++ Inside' sticker on it'"

  6. #6
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Circumstances where it is necessary to reuse a stream are pretty rare in practice.

    Generally, I tend to advocate doing no more than necessary. I certainly wouldn't bother to call some_stream.close() immediately before some_stream ceases to exist, since there is no way to destroy a stream object without closing it.

    Yes, I agree that a programmer should assume responsibility for cleaning up resources (ensuring streams are closed, etc) when no longer needed. However, C++ stream destructors do close themselves. So, by managing the lifetime of the stream object, I am doing all that is required to ensure streams are closed. Such is the beauty of RAII.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  7. #7
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Using scope to close is not always possible. To control where it is closed, you need to introduce a pair of curly braces. Any other variables you declare within those braces will also be destroyed at the closing brace, even if that's not what you wanted. That said, you can usually structure things so that the RAII pattern works for you.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  8. #8
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by brewbuck View Post
    Using scope to close is not always possible. To control where it is closed, you need to introduce a pair of curly braces.
    You've actually contradicted yourself here.

    Although, in practice, it is often easier to introduce a small function and call that, rather than just introducing a new scope in the middle of a function or other block.

    Quote Originally Posted by brewbuck View Post
    Any other variables you declare within those braces will also be destroyed at the closing brace, even if that's not what you wanted.
    If you are introducing new blocks to control the lifetime of a stream, and other variables are unintentionally being destroyed along with it, then you probably have a severe design problem. Even then, you can simply introduce additional blocks to control lifetime of those variables and move variable definitions to align their lifetime with their enclosing scope.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  9. #9
    Registered User rogster001's Avatar
    Join Date
    Aug 2006
    Location
    Liverpool UK
    Posts
    1,472
    If you are introducing new blocks to control the lifetime of a stream, and other variables are unintentionally being destroyed along with it, then you probably have a severe design problem.
    haha yea, but i think brewbuck was suggesting the dangers where some coders do not grasp their data's scope, thats how i read it anyway
    Thought for the day:
    "Are you sure your sanity chip is fully screwed in sir?" (Kryten)
    FLTK: "The most fun you can have with your clothes on."

    Stroustrup:
    "If I had thought of it and had some marketing sense every computer and just about any gadget would have had a little 'C++ Inside' sticker on it'"

  10. #10
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by rogster001 View Post
    haha yea, but i think brewbuck was suggesting the dangers where some coders do not grasp their data's scope, thats how i read it anyway
    Yes, but "programmer does not grasp what they're doing so does a shonky design" and "it is not possible to use scope to do ABC" are not equivalent statements.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  11. #11
    Registered User rogster001's Avatar
    Join Date
    Aug 2006
    Location
    Liverpool UK
    Posts
    1,472
    fair comment
    Thought for the day:
    "Are you sure your sanity chip is fully screwed in sir?" (Kryten)
    FLTK: "The most fun you can have with your clothes on."

    Stroustrup:
    "If I had thought of it and had some marketing sense every computer and just about any gadget would have had a little 'C++ Inside' sticker on it'"

  12. #12
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Quote Originally Posted by grumpy View Post
    If you are introducing new blocks to control the lifetime of a stream, and other variables are unintentionally being destroyed along with it, then you probably have a severe design problem. Even then, you can simply introduce additional blocks to control lifetime of those variables and move variable definitions to align their lifetime with their enclosing scope.
    This is not always possible. consider:
    Code:
    {
      ifstream file1 ("file1.txt");
      //read from file1 here
      ifstream file2 ("file2.txt");
      //use file1 and file2 here
      file1.close();
      //keep using file 2 here
    }
    Now you could do this:
    Code:
    ifstream file2
    {
      ifstream file1 ("file1.txt");
      //read from file1 here
      file2.open("file2.txt");
      //use file1 and file2 here
    }
    //keep using file 2 here
    But that vialates RAII too.

    Streams are the example, but they are not the only resouse that could encounter this problem.

    Although this problem isn't that common, I don't think it's invariably a design problem when it does come up.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  13. #13
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    Well these examples are getting a bit contrived so I don't think you can make any concrete statements about them. If I had 2 files to read I would do it with a little more finesse than just putting in blocks. I consider that to be one of the hackiest ways to control lifetime, and these examples aren't convincing me otherwise.

  14. #14
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    I don't think it's that uncommon to start to load a file, then observe that the data on the file needs another system resource, and load that reasource before finishing readding the file.

    For example the file might indicate that a large continious buffer is needed. I this case I would follow my second code snippet, but it does vioalate RAII, so it's not much better than the other way:
    Code:
    vector<Obj> buffer;
    {
      ifstream file1 ("file1.dat");
      //read header from file1 here  
      buffer.resize(10000);
      //fill buffer from file 1
    }
    //keep using the buffer
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  15. #15
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    Quote Originally Posted by King Mir View Post
    Code:
    ifstream file2
    {
      ifstream file1 ("file1.txt");
      //read from file1 here
      file2.open("file2.txt");
      //use file1 and file2 here
    }
    //keep using file 2 here
    But that vialates RAII too.
    I agree this example indeed shows where brackets are not useful. It implies though that file2 must be opened after file1 so something manual is required. Not a typical example.

    If you can open first file2 then brackets become better
    Code:
    ifstream file2("file2.txt")
    {
      ifstream file1 ("file1.txt");
      //use file1 and file2 here
    }
    //keep using file 2 here
    file1.read(...); //oops, but thankfully a compiler error
    where
    Code:
    ifstream file1 ("file1.txt");
    //read from file1 here
    ifstream file2 ("file2.txt");
    //use file1 and file2 here
    file1.close();
    //keep using file 2 here
    file1.read(...); //oops!
    Using a function is indeed cleaner and much more readable. But the idea is the same, you won't manually manage the closing of the file.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. when parent process close, how to close the child?
    By omega666 in forum C Programming
    Replies: 4
    Last Post: 04-06-2011, 12:23 AM
  2. manually sorting cards
    By cyberfish in forum A Brief History of Cprogramming.com
    Replies: 33
    Last Post: 05-16-2008, 09:09 AM
  3. Manually adding controls to a wnd and their functions.
    By earth_angel in forum Windows Programming
    Replies: 4
    Last Post: 08-22-2005, 06:26 PM
  4. uhm... calling a destructor manually
    By *ClownPimp* in forum C++ Programming
    Replies: 2
    Last Post: 09-11-2002, 02:37 PM
  5. Manually programming Press any key in vis C++
    By vanceypants in forum C++ Programming
    Replies: 1
    Last Post: 06-06-2002, 04:23 AM