错误Debug Assertion Failed - 删除动态分配的数组时

时间:2016-12-18 03:31:34

标签: c++ memory-management delete-operator

我一直在尝试完成课程作业,但我一直收到一个似乎无法解决的错误。 Debug Assertion failed我已经将问题(我认为)缩小到了析构函数。如果我注释掉delete[] english;行,则没有错误。我试过通过其他线程阅读,但他们没有帮助解决这个问题。这是项目中的三个文件(我取出了所有其余的代码,因为错误仍然只发生在这一点):

这是头文件:

//Dictionaty.h
#ifndef DICTIONARY_H
#define DICTIONARY_H

class Dictionary
{
public:
    Dictionary();
    ~Dictionary();

   void setEnglish(char*);
   char* getEnglish();


private:
    char *english;

};

#endif

这是函数的位置:

//dictionary.cpp
#include <iostream>
#include "Dictionary.h"

using namespace std;

Dictionary::Dictionary()
{
    english = new char[20];


    strcpy(english, " ");
    //strcpy(french, " ");
}

Dictionary::~Dictionary()
{
    delete[] english; // problem is here (i think)

}

void Dictionary::setEnglish(char *eng)
{
    english = eng;
    cout << "the value of english in \"setEnglish()\" is: " << english << endl; //db
}

这是驱动程序:

//dictionaryDrv.cpp
#include <iostream>
#include "Dictionary.h"

using namespace std;

int main()
{
    Dictionary words[30];

    //readIn(words);
    char test[5] = "test";
    words[0].setEnglish(test);


    system("pause");
    return 0;
}

4 个答案:

答案 0 :(得分:1)

显示的代码中存在多个错误。

english = new char;

这将english设置为一个字符的动态分配数组,然后立即:

strcpy(english, " ");

这会将两个char s - 一个空格和一个\0复制到一个只有一个字符的缓冲区中。这会在数组末尾运行,破坏内存,并导致未定义的行为。

此外,在析构函数中:

 delete[] english; 

这本身就没问题。不同的是:

void Dictionary::setEnglish(char *eng)
{
    english = eng;

由于从main()调用此结果,english被设置为指向未在动态范围中分配的缓冲区的指针。因此,析构函数将尝试deletenew的内容。这也会导致未定义的行为。

此外,展望未来,所显示的课程violates the Rule of 3,因此,它很容易错误地使用它,导致进一步的错误。

总之,显示的代码无法正确处理动态分配的内存,从覆盖未分配的内存到delete从未{{1}第一名。

您需要重读并研究C ++手册中有关如何正确使用动态分配内存的章节。

答案 1 :(得分:1)

问题是

char test[5] = "test";
words[0].setEnglish(test);

然后将成员varialbe english分配给从数组test衰减的指针,该指针不是使用new[]动态分配的,然后不能delete[]编辑,但这正是析构者试图做的事情。因此,UB。

根据您的代码的意图,您应该在strcpy中使用strncpyDictionary::setEnglish,不要直接指定指针。

其他建议:

  1. 考虑The Rule of Three,尤其是当您使用原始指针(例如char*)时。

  2. 使用std::string代替C风格的字符串(char*)。

答案 2 :(得分:0)

`char test[5] = "test";  words[0].setEnglish(test);`

这里测试是在堆栈中分配的(那里没有new)。然后english = eng;会将指针english指向它,你不能从堆栈中delete

修复:由于你希望你的对象拥有字符串,你应该复制它

void Dictionary::setEnglish(char *eng)
{
    delete[] english;
    english = new char[strlen(eng) + 1];
    strcpy(english, eng);
    cout << "the value of english in \"setEnglish()\" is: " << english << endl; //db
}

最后,最好使用std :: string并避免大量的头痛。

答案 3 :(得分:0)

问题是如何在setEnglish方法中设置值, english = eng 的分配不会以正确的方式分配值,因此,如果使用strcpy,则可以修复:< / p>

使用:

    void Dictionary::setEnglish(char *eng) {
        strcpy(english,eng);
        cout << "the value of english in \"setEnglish()\" is: " << english << endl; 
}

你会得到正确的行为