I was writing a RAII wrapper for FILE *. I noticed that when the FILE * is deleted after close in the destructor it leads to undefined behavior (seg. fault or errors somewhere else). I assumed that the fclose will set the FILE * to NULL, which it did not.
class smartFP {
smartFP (const std::string& name)
: fp (fopen(name.c_str(), "r")
{ }
~smartFP()
{
if (fp) {
fclose(fp);
// delete(fp); <- This is causing crash
fp = NULL; <- Is this OK?
}
}
private:
FILE *fp;
};
- Why does fclose not set the FILE * to NULL?
- The second question is does fopen allocate memory for fp in the heap or stack? I thought it does on heap and hence wanted to do a delete after fclose, so that the 4 or 8 bytes on heap for fp is de-allocated. But looks like this is not needed.
Of course
delete fpis causing a crash. It wasn’t allocated withnew. Only calldeleteon something you got withnewor with something else that the documentation told you to use it on. The documentation forfopennever tells you to usedelete. All cleanup for files is performed byfclose; there’s nothing additional you need to do to release file-related resources after you’ve called it.Setting
fp = NULLis fine. It’s probably desirable so that future consumers of this “smart file pointer” can check whether the pointer is still valid. (It’s more useful from aresetmethod than from the destructor, though; there can’t be any future consumers of the pointer class after the destructor has run because the object doesn’t exist anymore.) Butfclosecan’t do that itself becausefclosedoesn’t receive its parameter by reference, and even if it did, it wouldn’t be able to invalidate all possible copies of the file pointer. Recall thatfreeanddeletedon’t set their arguments toNULL, either.