为什么fclose没有将文件指针设置为NULL?

时间:2011-09-01 21:58:27

标签: c++ pointers fclose

我正在为FILE *编写RAII包装器。我注意到,当在析构函数中关闭后删除FILE *会导致未定义的行为(seg。错误或其他地方的错误)。我假设fclose会将FILE *设置为NULL,但事实并非如此。

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;
};
  • 为什么fclose没有将FILE *设置为NULL?
  • 第二个问题是fopen在堆或堆栈中为fp分配内存吗?我认为它在堆上做了,因此想在fclose之后进行删除,这样fp的堆上的4或8个字节就被解除分配了。但看起来这不是必需的。

5 个答案:

答案 0 :(得分:14)

当然delete fp导致崩溃。它没有分配new。只能使用delete或使用文档告诉您使用的其他内容来调用newfopen的文档从未告诉您使用delete。文件的所有清理都由fclose执行;在调用文件相关资源之后,您无需执行任何其他操作。

设置fp = NULL很好。可能需要这样的“智能文件指针”的未来消费者可以检查指针是否仍然有效。 (但是从reset方法比从析构函数更有用;在析构函数运行后,指针类的任何未来消费者都不会因为该对象不再存在而存在。)但是{{1因为fclose没有通过引用接收它的参数,所以它本身不能这样做,即使它没有,它也无法使所有可能的文件副本无效指针。回想一下,fclosefree也不会将其参数设置为delete

答案 1 :(得分:2)

不,你不应该尝试delete一个文件*。它是一个C库数据结构,并不代表从C ++ new返回的指针。

答案 2 :(得分:2)

fp不是由C运行时分配的,您不必释放它。 fclose不会将其设置为NULL,因为它无法将其设置为null(它是指向FILE结构的指针,而不是指向FILE *)。

如何分配FP并不是您关心的问题,它不是您与API合约的一部分,所以不要担心。

附录:

fopen返回一个指向FILE结构的指针。它在何处以及如何获得记忆并不重要。它很可能指向内存中的静态结构。但是,基本上,你不应该对那个记忆负责,所以你不应该搞乱它。

现在,实际的fp指针,你可以分配:

FILE **fp = malloc(sizeof(FILE *));
*fp = fopen("file.txt", "r");
...
fclose(*fp);
free(fp);

但是,显然,大多数人不这样做,他们只是使用本地堆栈变量来管理它。取决于用例。

答案 3 :(得分:1)

fopenfclose使用FILE *元素进行必要的动态内存管理,因此您无需在其上调用delete。但是,如果需要,可以在其中添加NULL值,以表示未分配文件。

答案 4 :(得分:1)

1)fclose 无法将FILE *设置为NULL,因为它的参数是FILE *,因此它按值收到FILE *。由于它是一个副本,它不能改变你的指针,除非参数被改为FILE *&amp;。
2)在C ++中,除非你调用delete,否则几乎不会调用new。如果您正在进行RAII,则只应将new分配给智能指针,并且永远不要再调用delete