繁体   English   中英

删除char指针在析构函数中不起作用

[英]Delete char pointer not working in destructor

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

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;并在file.close() fileName被删除后将其放在ReadFile() ,为什么呢?

我的程序的其余部分工作正常,这就是为什么没有粘贴任何代码的原因。 我只是想摆脱任何内存泄漏,而fileName是我遇到的唯一麻烦,因此我只将代码粘贴到使用fileName的地方。

任何帮助表示赞赏。

附加信息:我正在使用Visual Studio编写此代码,并且正在使用内存泄漏检测。 这是它的输出:

检测到内存泄漏!
转储对象->
{132} 0x005D49A0的正常块,长40个字节。
数据:6E 61 6D 65 73 2E 74 78 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中使用-那么我建议您从Program类中将其删除,并在该函数中使其成为自动变量:

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

您的问题可能与

  1. 未在构造函数中将文件名初始化为nullptr
  2. 未定义复制c-tor,赋值运算符
  3. 您没有删除readFile中的旧文件名

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

如果必须具有该成员变量-将其更改为数组-不要分配它:

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

[UPDATE]

您的.h文件不正确-违反了三个规则(请参阅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];

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

fileName显然已被删除:析构函数中的代码如此表示。 但是,如果您未显示的代码多次调用ReadFile ,则该类将泄漏内存,因为对ReadFile每次调用都会分配一个新的内存块,并覆盖指向前一个块的指针。

思考RAII:资源分配就是初始化。 在构造函数中,分配内存块。 在析构函数中,将其删除。 然后, ReadFile不必担心分配块。

或者,甚至更好,按照@PiotrNycz的说明进行操作,然后将指针更改为数组。 无需动态分配。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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