调用delete []会导致程序崩溃,但调试时则不会

use*_*359 1 c++ crash

这是一个简单程序的代码,它应该读取每行包含一个单词的文本文件,动态分配存储所有单词所需的内存,将它们打印在屏幕上并释放所使用的内存.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

class Dict {
 public:
 int size;
 char ** words;
 Dict (int, int*);
 ~Dict ();
};

Dict::Dict(int s,int* sizes) {
 int i;
 size=s;
 words = new char* [s];
 for (i=0;i<s;i++)
  words[i] = new char [sizes[i]];
}

Dict::~Dict() {
 int i;
 for (i=0;i<size;i++) {
  delete [] words[i];
  printf("i=%d\n",i); // for debugging
  }
 delete [] words;
}

Dict loadDict (char* filename) {
 FILE* file;
 int n=0,i=0;
 int * sizes;
 char buff [64];

 file=fopen(filename,"r");
 while (!feof(file)) {
  n++;
  fscanf(file,"%*[^\n] \n");
 }
 sizes=new int [n];

 rewind(file);
 while (!feof(file)) {
  if (fscanf(file,"%s\n",buff)>0) {
   sizes[i]=strlen(buff);
   i++;
  }
 }

 rewind(file);
 Dict r(n,sizes);
 i=0;
 while (!feof(file)) {
  fscanf(file,"%s\n",r.words[i]);
  i++;
 }

 delete [] sizes;
 return r;
}

int main() {
 int i;
 Dict d=loadDict("dict.txt");
 for (i=0;i<d.size;i++)
 printf("%s|\n",d.words[i]);
 printf("%d DONE.\n",d.size);
 return 0;
}
Run Code Online (Sandbox Code Playgroud)

解除分配是在Dict类的析构函数中完成的.但是,在只有几个单词的示例文本文件上使用时,单词被正确打印,但是~Dict在执行表单的3行之后调用应用程序会崩溃delete [] words[i];.如果我使用Code :: Block的调试器并在该行上设置断点并告诉它在每个断点上继续,程序将正常终止.

由于这是一个非常简单的程序,我希望有一些简单的答案或修复!

hmj*_*mjd 7

Dict类已动态分配的成员,但使用默认复制构造和赋值操作符,这导致的两个实例Dict指向同一words时的副本阵列Dict制成,所述时恰好loadDict()被使用的功能.当其中一个Dict实例被破坏时,它会使另一个Dict实例留下悬空指针,并导致words数组及其元素的双重删除.

什么是三规则?

如果这不是一个学习练习,请使用std::vector<std::string>C++流.例如:

std::vector<std::string> words;
...

std::ifstream in(filename);
std::string line;
while (in >> line) words.push_back(line);
Run Code Online (Sandbox Code Playgroud)