删除不在析构函数中工作的char指针

时间:2012-10-20 23:29:03

标签: c++ destructor delete-operator

我有一个程序,我向用户询问文本文件的名称,我打开文本文件做它的东西(读,写),然后我关闭文件并退出程序。

Program.h

class Program
{
     char* fileName;
public:
     Program();
     ~Program();
     void ReadFile(void);
};

Program.cpp

Program::Program(){
     //contstructor
     fileName=NULL;
}

Program::~Program(){
     cout << "in destructor" ;
     delete []fileName;
}

void Program::ReadFile(void){
     fileName = new char[40];

     cout <<"Please enter the name of the file to open: ";
     cin.clear();
     cin.getline(fileName, 40);

     ifstream file (fileName);

     if(file.is_open()){
          //do stuff
     }
     file.close();
}

现在,当我将delete []fileName;放入析构函数中时,它会在屏幕上输出“”in destructor“,但fileName不会被删除。如果我将delete []fileName;放入ReadFile()file.close() fileName被删除之后。为什么会这样?

我的程序的其余部分完美地工作,这就是为什么没有粘贴代码的原因。我只是试图消除任何内存泄漏,fileName是唯一一个我遇到问题的因此,因此我只粘贴了使用fileName的代码。

感谢任何帮助。

其他信息: 我正在使用Visual Studio编写此内容并使用内存泄漏检测。这是它输出的内容:

  

检测到内存泄漏!
  倾倒物体 - &gt;
  {132}正常阻塞位于0x005D49A0,长度为40个字节    数据:6E 61 6D 65 73 2E 74 78 74 00 CD CD CD CD CD CD   对象转储完成。
  程序'[10772] program1.exe:Native'已退出,代码为0(0x0)。

这就是为什么我怀疑delete []fileName;无效。

此外,这是int main()的样子

int main(){
     Program abc;
     abc.ReadFile();
}

哦,并且Program.h无法更改。只有.cpp可以改变它是我的要求的一部分。

3 个答案:

答案 0 :(得分:3)

如果filename只在readFile中使用 - 那么我建议你从Program类中删除它并使它在该函数中自动变量:

void Program::ReadFile(void){
     char fileName[40];
     ...
     file.close();
     // no delete [] necessary
}

您的问题可能与

有关
  1. 未在构造函数
  2. 中将filename初始化为nullptr
  3. 未定义复制c-tor,赋值运算符
  4. 您没有删除readFile中的旧文件名
  5. 因此,不要将您的成员变量用作方法的自动变量。

    如果必须将此成员变为可变 - 将其更改为数组 - 请不要分配它:

    class Program {
    private:
      // char* filename;
      char filename[40];
    }; 
    

    [UPDATE]

    您的.h文件不正确 - 它违反了规则3(请参阅http://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming)) - 复制构造函数和赋值运算符丢失。因此,请注意不要以任何方式复制您的Program类,否则无法更改此标题。

    更新后,程序中只缺少一件事:

    在readFile的开头添加delete[] filename

    void Program::ReadFile(void){
         delete [] filename;
         fileName = new char[40];
    

    或(更好) - 每次调用readFile时都不要重新分配:

    void Program::ReadFile(void){
         if (!filename)
             fileName = new char[40];
    

    或(最佳) - 仅在构造函数中分配此内存:

    Program::Program() : filename(new char[40]) {}
    void Program::ReadFile(void){
       // fileName = new char[40];
    

答案 1 :(得分:1)

您确定main与此处发布完全一致吗?如果您只是全局定义abc,它将在内存转储报告内存泄漏后释放,您可能会看到无效的报告!您可以在析构函数中插入断点,并查看在析构函数之后或之前是否报告了内存泄漏

答案 2 :(得分:0)

显然正在删除

fileName:析构函数中的代码是这样说的。但是如果您没有多次调用代码ReadFile,则该类将泄漏内存,因为每次调用ReadFile都会分配一个新的内存块并覆盖指向前一个块的指针。

认为RAI​​I:资源分配是初始化。在构造函数中,分配内存块。在析构函数中,删除它。然后ReadFile不必担心分配块。

或者,甚至更好,就像@PiotrNycz所说,并将指针更改为数组。无需动态分配。