删除Char指针在destructor中不起作用

Delete char pointer not working in destructor

本文关键字:不起作用 destructor Char 指针 删除      更新时间:2023-10-16

我有一个程序,在该程序中我向用户询问文本文件的名称,我打开文本文件对其进行操作(读,写),然后我关闭文件并退出程序。

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",但文件名不会删除。如果我服用delete []fileName;并将其放入file.close() FILENAME后将其放入ReadFile()中。P>

我的其他程序的其余部分正常工作,这就是为什么该代码都没有粘贴的原因。我只是想摆脱任何内存泄漏,文件名是我唯一遇到的麻烦的,因此我只粘贴了使用文件名的代码。

任何帮助将不胜感激。

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

检测到的内存泄漏!
倾倒对象 ->
{132}正常块在0x005d49a0,40字节长。
数据:6e 61 6d 65 73 2e 74 74 74 00 CD CD CD CD CD CD CD
对象转储完成。
程序'[10772] program1.exe:本机'已使用代码0(0x0)退出。

这就是为什么我怀疑delete []fileName;不起作用。

另外,这就是int main()的样子

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

哦,program.h无法更改。只有.cpp可以更改,这是我要求的一部分。

如果仅在readfile中使用文件名 - 那么我建议您将其从程序类中删除,并在该函数中自动变量:

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

您的问题可能与

有关
  1. 不在constructor中将文件名初始化为nullptr
  2. 未定义副本c-tor,分配操作员
  3. 您没有在ReadFile中删除旧文件名

因此,请勿将您的成员变量用作自动变量的方法。

如果您必须让此成员可变量 - 将其更改为数组 - 请勿分配:

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

[更新]

您的.h文件不正确 - 它破坏了三个规则(请参阅http://en.wikipedia.org/wiki/rule_of_three_(C++_programming)) - 复制构造函数和分配运算符。因此,请注意不要以任何方式复制您的程序类,无法更改此标头。

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

在您的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];

您确定您的main是否完全如这里发布的吗?如果您只是在全球定义abc,则将在内存转储报告内存泄漏后将其释放,您可能会看到无效的报告!您可以在破坏者中插入一个断裂点,查看记忆是否在破坏者之后或之前报告的内存泄漏

fileName显然已被删除:destructor中的代码是这样。但是,如果您未一次显示ReadFile的代码,则类将泄漏内存,因为每个调用ReadFile都会分配一个新的内存块并覆盖指针到上一个块。

思考RAII:资源分配是初始化。在构造函数中,分配内存块。在破坏者中,将其删除。那么ReadFile不必担心分配块。

或者更好,如@piotrnycz所说,将指针更改为阵列。无需动态分配。