1

我所有的程序都因为 , , 而崩溃delete [] meanings;delete [] meanings;delete [] temp_meaning;我删除这 3 行时它工作正常,所以可能我错误地使用了 delete ... 有人可以在这里启发我吗?

#include <iostream>
#include <string>
#include <cstring>
using namespace std;

class Expression {

    char *word_with_several_meanings; // like "bank", "class"
    char **meanings; // a pointer to a pointer stores all meanings
    int meanings_ctr; // meanings counter

    //-----------FUNCTIONS------------------------------------------------
public:
    void word(const char* = NULL );
    void add_meaning(char * = NULL);
    char* get_word();
    int get_total_number_of_meanings();
    char* get_meaning(int meanx = 0);
    Expression(int mctr = 0); // CTOR
    ~Expression(); // DTOR
};

Expression::Expression(int mctr ) {
    meanings_ctr = mctr;    // Setting the counter to 0
    meanings = new char * [meanings_ctr]; // Allocate Space for meanings
}

Expression::~Expression() {

    while(meanings_ctr-->0){
    delete meanings[meanings_ctr];
    }
    delete [] meanings; // Deleting the memory we allocated
    delete [] word_with_several_meanings; // Deleting the memory we allocated
}

void Expression::word(const char *p2c )
{

    word_with_several_meanings = new char[strlen(p2c)+1];
    // copy the string, DEEP copy
    strcpy(word_with_several_meanings, p2c);
}

void Expression::add_meaning( char  * p2c)
{

    //meanings[ meanings_ctr ] = new char [strlen(p2c) + 1];
    //strcpy(meanings[ meanings_ctr++ ] , p2c);
    // temp 
    if (meanings_ctr < 1){
    meanings[ meanings_ctr ] = new char [strlen(p2c) + 1];
    strcpy(meanings[ meanings_ctr++ ] , p2c);
    }
    else {
int temp_ctr;
    char **temp_meaning;
    temp_meaning = new char * [meanings_ctr-1];
    for(temp_ctr =0; temp_ctr<meanings_ctr;temp_ctr++){
        temp_meaning[temp_ctr] = new char [strlen(meanings[ temp_ctr ]) + 1];
            strcpy(temp_meaning[temp_ctr], meanings[ temp_ctr ]);
    }
    for (temp_ctr =0; temp_ctr<meanings_ctr;temp_ctr++){
            delete meanings[temp_ctr];

    }
    delete [] meanings;

    meanings = new char * [meanings_ctr];
    for(temp_ctr =0; temp_ctr<meanings_ctr;temp_ctr++){
        meanings[ temp_ctr ] = new char [strlen(temp_meaning[temp_ctr]) + 1];
            strcpy(meanings[ temp_ctr ], temp_meaning[temp_ctr]);
    }
    meanings[ meanings_ctr ] = new char [strlen(p2c) + 1];
    strcpy(meanings[ meanings_ctr ] , p2c);
            for (temp_ctr =0; temp_ctr<meanings_ctr;temp_ctr++){
            delete temp_meaning[temp_ctr];
    }
    delete [] temp_meaning;
            meanings_ctr++;
    }


}

char * Expression::get_meaning( int meanx )
{

    return *(meanings+meanx);

}

char * Expression::get_word()
{

    return word_with_several_meanings;

}

int Expression::get_total_number_of_meanings()
{
    return meanings_ctr;
}


int main(void) {
    int i;
    Expression expr;
    expr.word("bank");
    expr.add_meaning("a place to get money from");
    expr.add_meaning("b place to sit");
    expr.add_meaning("4 letter word");
    expr.add_meaning("Test meaning");
    cout << expr.get_word() << endl;

    for(int i = 0; i<expr.get_total_number_of_meanings(); i++)
            cout << " " << expr.get_meaning(i)  << endl;
    Expression expr2;
    expr2.word("class");
    expr2.add_meaning("a school class");
    expr2.add_meaning("a classification for a hotel");
    expr2.add_meaning("Starts with C");
    cout << expr2.get_word() << endl;
    for( i = 0; i<expr2.get_total_number_of_meanings(); i++)
            cout << " " << expr2.get_meaning(i) << endl;

    Expression expr3;
    expr3.word("A very long test");
    char str[] = "Meaning_    ";
    for(int kx =0; kx<31; kx++){
            str[8] = ('A'+kx);
            expr3.add_meaning(str);
    }

    cout << expr3.get_word() << endl;
    for( int i = 0; i<expr3.get_total_number_of_meanings(); i++)
            cout << " " << expr3.get_meaning(i) << endl;
    return 0;
}
4

2 回答 2

4

该程序显示出来自以下语句的内存损坏迹象:

    meanings_ctr = mctr;    // Setting the counter to 0
    meanings = new char * [meanings_ctr]; // Allocate Space for meanings

    meanings = new char * [meanings_ctr];

由于 add_meaning() 包含以下代码:

if (meanings_ctr < 1){
   meanings[ meanings_ctr ] = new char [strlen(p2c) + 1];

您实际上是在含义 [0] 上写的,而您为它分配了 0 个字节。由于 C 中的索引从 0 开始,对于具有最高索引的数组,max_index您需要分配max_index+1元素。对于一个数组,max_index = 0您需要分配 1 个元素。

换句话说,您需要分配meanings = new char * [meanings_ctr + 1]而不是new char * [meanings_ctr],而temp_meaning = new char * [meanings_ctr]不是new char * [meanings_ctr - 1]

至于使用deletedelete[]一般规则是分配的new应该被释放,delete分配的new[]应该被销毁delete[]。上面有一个线程:delete vs delete[] operator in C++在delete how dos know it is an array的答案中可以找到一些好的背景。

以下是如何在不使用任何昂贵的工具或难以学习的工具的情况下调试程序。

如果您将调试打印添加到构造函数和析构函数中,如下所示:

Expression::Expression(int mctr ) {
    meanings_ctr = mctr;    // Setting the counter to 0
    meanings = new char * [meanings_ctr]; // Allocate Space for meanings
    cout << "[debug] allocated " << sizeof(char*)*meanings_ctr << " bytes @" << 
             hex << meanings << dec << endl;
}

Expression::~Expression() {
    while(meanings_ctr-- > 0){
//       if(meanings[meanings_ctr]) delete [] (meanings[meanings_ctr]);
    }
    cout << "[debug] to deallocate @" << hex << meanings << dec << endl;
//   delete [] meanings; // Deleting the memory we allocated
//    delete [] word_with_several_meanings; // Deleting the memory we allocated
}

同样在 add_meaning() 中,你得到

[debug] allocated 0 bytes @0x804c008
[debug] to deallocate @0x804c008
[debug] allocated 4 bytes @0x804c078
 ...
[debug] allocated 120 bytes @0x804fa78
[debug] to deallocate @0x804fa78
[debug] to deallocate @0x804c260
[debug] to deallocate @0x804c150

这里看起来令人担忧的是allocated 0 bytes。由于 add_meanings() 中的代码包含:

if (meanings_ctr < 1){
meanings[ meanings_ctr ] = new char [strlen(p2c) + 1];

它使用未分配的内存 @meanings[0]并导致损坏。

以下是所有累积的更改以供参考:

25c25
<     meanings = new char * [meanings_ctr]; // Allocate Space for meanings
---
>     meanings = new char * [meanings_ctr + 1]; // Allocate Space for meanings
30,31c30,31
<     while(meanings_ctr-->0){
<     delete meanings[meanings_ctr];
---
>     while(meanings_ctr-- > 0){
>         delete [] meanings[meanings_ctr];
58c58
<     temp_meaning = new char * [meanings_ctr-1];
---
>     temp_meaning = new char * [meanings_ctr ];
64c64
<             delete meanings[temp_ctr];
---
>          delete [] meanings[temp_ctr];
69c69
<     meanings = new char * [meanings_ctr];
---
>     meanings = new char * [meanings_ctr + 1];
76,77c76,77
<             for (temp_ctr =0; temp_ctr<meanings_ctr;temp_ctr++){
<             delete temp_meaning[temp_ctr];
---
>     for (temp_ctr =0; temp_ctr<meanings_ctr;temp_ctr++){
>            delete [] temp_meaning[temp_ctr];
于 2012-05-01T13:05:35.677 回答
3

你必须来自 C 世界,你不会char*在 C++ 程序中找到任何存储单词的东西......你应该看看std::string,它会启发你的一天,我可以向你保证。

顺便说一句,在 C++ 中,我们倾向于摆脱所有这些delete,并且delete [],您也许应该选择一本好的 C++ 书籍并学习正确的 C++,而不是 30 年前使用的带有类的 C。

于 2012-05-01T12:27:58.037 回答