简体   繁体   中英

Closing files using fstream

If you open a file and then close it. Why does the program compile if you try to close an already closed file?

for example

ifstream inFile;
inFile.open("filename");
inFile.close();
inFile.close();

Why doesn't the compiler recognize that you already closed the file?

Why doesn't the compiler recognize that you already closed the file?

These statements are syntactically correct, so the compiler won't complain.

Theoretically the second close() call might fail at runtime, but since its an idempotent operation, it won't.

As you can see from the reference documentation :

Notes

This function is called by the destructor of basic_fstream when the stream object goes out of scope and is not usually invoked directly.

It must even be implemented idempotentially.

The standard clearly specifies exactly what happens if you call close() on a fstreambuf that isn't open (there is no effect, ie it does nothing), so it's not an error at run-time, and so it would be totally wrong for the compiler to refuse to compile such code.

In any case, the compiler doesn't check things like that in C++. Let's imagine a world where C++ works like you expect. If you have a function like this:

void close(std::ifstream& f);

Which happens to be implemented (in some other file) as:

void close(std::ifstream& f) { f.close(); }

And you change your code to:

ifstream inFile;
inFile.open("filename");
close(inFile);
inFile.close();

Then it would compile OK, because the compiler can't "see" that the first call closes the file. But if the close(std::fstream&) function was inline, is the compiler expected to now reject it? Or would it only be an error when called directly within a single function? The world you imagine is difficult to work with and difficult to specify. It would make code very fragile and context-sensitive, and make refactoring difficult.

C++ doesn't work like that, and that's a good thing.

Your imagined world would also require the compiler to "understand" what inFile.close() means . As far as the compiler is concerned it just executes a sequence of operations, finally resulting in some call like fclose(fp) or close(fd) , but that will be nested inside several levels of function calls, possibly not inline. Even if they were all inline the compiler doesn't "understand" the meaning and effects of every operation, it just compiles what you write and calls the functions you tell it to call. How do you expect it to "know" what all that code actually means ?

Taking an incredibly simple where the compiler does understand the meaning of every operation:

int i = 1;
int* p = &i;
int j = *p;
p = nullptr;
int k = *p;

The compiler won't even reject this, even though the second *p has undefined behaviour. It's your job not to write that code, not the compiler's job to catch it.

The kind of error that this kind of code might produce is a runtime exception. The compiler is not concerned with such things. Instead, it parses your code into object files for subsequent linking. To produce these object files, your code need only be syntactically correct and well-formed with respect to your chosen language.

So only after your object files are linked into a library or executable and then executed, will a runtime exception occur.

Perhaps the answer is: the compiler does not know or care about the runtime behaviour of your code and the kind of error you are alluding to is a runtime one.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM