1

I have ifstream and an ofstream that in runtime might be opened or not (depends on what the user enters in command line. i declare the variables anyway, and i have a method that opens the stream if needed. my problem is at the end of the program i don't know if i need to close them or not.

Is there anyway in c++ to know if a stream was opened? Like in Java you can give a stream the null value and then ask if its null (it means that it was never opened)..

Is it ok to close a stream that was never opened?

this is the code:

int main(int argc, char* argv[]) {

    static std::ifstream ifs;
    static std::ofstream ofs;

        //might or might not open the streams:
    OpenStreams(ifs,ofs,argc-1,argv);
        ........

        //here i would like to close the streams at the end of the program
        //or not (if they were not opened

    return 0;

}

Thanks!

Mike
  • 413
  • 1
  • 3
  • 13

6 Answers6

3

I don't really know, nor care to look. Just leave it to the destructors, the standard file streams will close the files during destruction if needed.

EDIT: On lifetimes of objects and guaranteed destruction...

To follow up the second comment to Ben Voigt that I wrote, this is a small test on object lifetimes:

#include <cstdlib>
#include <iostream>
#include <string>

struct test {
    std::string name;
    test( std::string const & name ) : name(name) {
        std::cout << "test " << name << std::endl;
    }
    ~test() { std::cout << "~test " << name << std::endl; }
};

void foo( bool exit ) {
    test t1( "1" );
    static test t2( "2" );
    test t3( "3" );
    if ( exit ) {
        std::exit(1);
    }
}
int main()
{
    foo(false);
    std::cout << std::endl;
    foo(true);
}

And the result of the execution:

test 1
test 2
test 3
~test 3
~test 1

test 1
test 3
~test 2

It can be seen that during the first execution the construction of the objects in foo occurs in the same order as the code., but when the function exits only the objects with auto storage get destroyed, with the object with static storage outliving the function execution.

In the second call to foo, the auto objects get recreated, while the static object doesn't, as expected, since it was created in a previous call. Because foo calls exit() in the second call, the auto objects in foo don't get destructed. On the other hand, the static object is correctly destructed.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
  • +1 for leave it to the destructors, but this might require changing the lifetime from `static` to automatic. – Ben Voigt Sep 16 '10 at 17:43
  • I'm opening the streams with the command: ifs.open(fileName); – Mike Sep 16 '10 at 17:44
  • will it be closed by the destructor also? – Mike Sep 16 '10 at 17:44
  • @Ben Voigt: I did find strange the `static` lifetime qualification, but that is not really an issue in this case. Since the function is `main`, the lifetime of an `auto` variable or a `static` function variable is basically the same: once main completes the local auto objects will be destroyed in reverse order of construction. Then static objects will start to get destroyed in reverse order of destruction. This might imply that the destruction of other objects created earlier in `main` is performed before destruction of the streams, but that should not be an issue. – David Rodríguez - dribeas Sep 16 '10 at 17:50
  • @Ben Voigt: ... also note that there is a real advantage in having the streams have `static` storage duration. In the presence of a call to `abort()` or `exit()`, `static` objects are guaranteed to get destructed, while `auto` objects may not be destructed. – David Rodríguez - dribeas Sep 16 '10 at 17:51
  • @Mike: it does not matter how you open the streams, the stream class knows whether it is open or not and will handle it. – David Rodríguez - dribeas Sep 16 '10 at 17:52
  • @Ben Voigt: I have edited the question with a short test of object lifetimes. – David Rodríguez - dribeas Sep 16 '10 at 18:03
  • @David: Is destruction of global objects and static objects in other functions interleaved with destruction of static objects in main? I'm worried that some global object used by iostreams could get destroyed before the destructors run for these variables. – Ben Voigt Sep 16 '10 at 18:03
  • Also, I'm pretty sure that if `abort()` is called, destructors of objects with static storage duration are guaranteed not to be called. That's pretty much the whole point of `abort` after all. – Ben Voigt Sep 16 '10 at 18:06
  • The destruction of static objects should be performed in reverse order of creation. All globals (and class statics) are created in an undefined order before entering main, and they are destroyed in the reverse order. Static objects local to functions are constructed when the definition is first encountered, and again destroyed in reverse order. On your particular concern, if that global was created before entering `main`, it will be destroyed after the `static` objects declared in `main`. – David Rodríguez - dribeas Sep 16 '10 at 18:09
  • @Ben Voigt: Right, I stand corrected: `abort()` exits the program without destroying static objects. It's a pity that comments cannot be easily edited :) – David Rodríguez - dribeas Sep 16 '10 at 18:10
  • Thanks for clarifying the destruction order. And I agree about the comment edits, although I can understand why it's not allowed (replies would make no sense at all). – Ben Voigt Sep 17 '10 at 01:16
1

Why not just test this using is_open() before you issue the close()?

Steve Townsend
  • 53,498
  • 9
  • 91
  • 140
  • Actually you would be better following advice elsewhere to let stream destructors handle this, unless you absolutely need to know the state of the file streams at closedown, or if you plan to reuse the streams objects. All the best. – Steve Townsend Sep 16 '10 at 17:50
0

Just don't make the variables static, that way they automatically close when main() returns.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
0

You can use the is_open method to test if a stream has been opened, then close it.

Diego Sevilla
  • 28,636
  • 4
  • 59
  • 87
0

Why not set a flag before opening a stream. Check the flag again if you need to close the stream object if any.

Better would be to pass that open stream object to the flag while opening a stream & use it to close the stream. If the flag has not been initialized or is null don't close.

loxxy
  • 12,990
  • 2
  • 25
  • 56
  • -1 for elaborating already incorrect answer via an edit that makes it more incorrect. – Steve Townsend Sep 16 '10 at 17:47
  • Well you see I was editing when you wrote the comment. Anyway is_open is what should be used...I didn't know of it. Peace mate :) – loxxy Sep 16 '10 at 17:47
0

No close call needed - the streams close itself when they are open when they are destroyed. Also, the static there looks suspicious. main is called only once, so it doesn't have any effect here (apart from pedantic standardese differences that don't matter here, i think.... Definitely not in the case shown).

That said, you can just call close if a stream is not opened - close will return a null pointer if it wasn't open. (I was looking at the spec for basic_filebuf<>::close - the file streams's close returns void).

File-streams can also handle non-open streams: If the stream wasn't open, it sets the failbit. You can check for that using fail() (which tests whehter the failbit or badbit is set). But there is is_open anyway to test whether the stream is open, but you don't need it for the above reasons.

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • About the static, in my exercise description it is advised to declare them as static because declaring them as automatic tends to generate Segmentation Fault. Maybe its because i'm using redirections to std::cin\cout with rdbuf – Mike Sep 16 '10 at 17:49
  • 2
    @Mike if that's the case, that must be the worst exercise description ever been written. – Johannes Schaub - litb Sep 16 '10 at 17:52
  • 1
    @Johanes: While at first I found *funny* using `static` for the streams, there is an advantage if any code in `main` can `exit()`. By having `static` storage duration, the streams are guaranteed to be destroyed even in the event of `exit()`, while they would not be destroyed and thus closed if they had auto storage.... Then again, if they had explained this in their course I would be impressed and kudos to the professor, if they did provide the explanation that @Mike suggests I agree with you... horrible teaching methodology. – David Rodríguez - dribeas Sep 16 '10 at 18:05
  • 1
    @Mike: You know, I hadn't read a good horror story recently, but your statement about your exercise description qualifies. If declaring input and output streams as automatic variables causes segfaults, there's something very seriously wrong, and the right thing to do is to figure out what and exorcise it. – David Thornley Sep 16 '10 at 18:10
  • @David that's what I thought of when i said "pedantic standardese differences". So that I wouldn't have to change my answer when someone knows the deep sheers of Standardese and comments on it :) See http://stackoverflow.com/questions/397075/what-is-the-difference-between-exit-and-abort/397081#397081 . I like how one can link to some prior made SO answer for basically anything that comes up :) – Johannes Schaub - litb Sep 16 '10 at 18:19
  • @Mike: `rdbuf` returns a pointer to the old buffer you are replacing. Before the replacement gets destroyed, you need to call `rdbuf` again to re-install the old one. – Potatoswatter Sep 16 '10 at 18:57