0

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

程序.h

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

程序.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不会被删除。如果我在fileName被删除后将delete []fileName;其放入。为什么会这样?ReadFile()file.close()

我的程序的其余部分运行良好,这就是为什么没有粘贴任何代码的原因。我只是想消除任何内存泄漏,而 fileName 是我唯一遇到的问题,因此我只粘贴了使用 fileName 的代码。

任何帮助表示赞赏。

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

检测到内存泄漏!
转储对象 ->
{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 可以更改,这是我的要求的一部分。

4

3 回答 3

3

如果文件名仅在 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];
}; 

[更新]

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

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

delete[] filename在 readFile 的开头添加:

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];
于 2012-10-20T23:37:42.530 回答
1

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

于 2012-10-21T00:33:23.833 回答
0

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

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

或者,更好的是,按照@PiotrNycz 的说法,将指针更改为数组。无需动态分配。

于 2012-10-20T23:54:27.243 回答