为什么我不能使用“delete”关键字来回收动态分配的内存呢?

时间:2021-08-28 21:17:06

I have the following class:

我有以下课程:

class Patient {
public:
    Patient(int x);
    ~Patient();
private:
    int* RP;
};

Patient::Patient(int x) { RP = new int [x]; }
Patient::~Patient() { delete [] RP; }

I create an instance of this class on the stack as follows:

我在堆栈上创建了这个类的实例,如下所示:

void f() { Patient p(10); }

Now, when f() returns, I get a "double free or corruption" error, which signals to me that something is attempted to be deleted more than once. But I don't understand why that would be so. The space for the array is created on the heap, and just because the function from inside which the space was allocated returns, I wouldn't expect the space to be reclaimed.

现在,当f()返回时,我得到一个“double free或corruption”错误,这向我表明某些内容试图多次删除。但我不明白为什么会这样。数组的空间是在堆上创建的,仅仅因为分配空间的函数返回,我就不会期望空间被回收。

I thought that if I allocate space on the heap (using the new keyword), then the only way to reclaim that space is to use the delete keyword. Help!

我认为如果我在堆上分配空间(使用新的关键字),那么回收该空间的唯一方法就是使用delete关键字。的帮助!

As requested, here is the actual code (slightly abridged for brevity's sake)

按照要求,这里是实际的代码(为了简短起见,略作删减)

Here's the full class definition (split across a .cpp and .h file, but shown together):

这里是完整的类定义(在.cpp和.h文件中拆分,但同时显示):

class Patient {

public:
    Patient(int numDecisionEpochs);

    ~Patient();

    void recordRP(const int& age, const bool& t);
    void recordBiopsy(const int& age, const int& result);
    void recordPSA(const int& age, const double& level);
    void recordPSA(const int& age);
private:
    int* RP;
    int* Biopsy;
    double* PSA;
};

Patient::Patient(int numDecisionEpochs) {
    RP = new int [numDecisionEpochs];
    Biopsy = new int [numDecisionEpochs];
    PSA = new double [numDecisionEpochs];
}

Patient::~Patient() {
    delete[] RP;
}

void Patient::recordRP(const int& age, const bool& t) {
    if(t)
    RP[age-1] = 1;  // RP either yes (1) or no (0)
    else
    RP[age-1] = 0;
}

void Patient::recordBiopsy(const int& age, const int& result) {
    switch(result)
    {
    case 0:
    case 1:
    case 2:
    case 3:
    case 4:
        Biopsy[age-1]=result; // only permit results 0,1,2,3,4
        break;
    default:
        cerr << "Invalid biopsy result (" << result << ") at age " << age << "!\n";
    }
}

void Patient::recordPSA(const int& age, const double& level) {
    PSA[age-1] = level; // record PSA volume
}

void Patient::recordPSA(const int& age) {
    PSA[age-1] = -1; // symbol for no screening during epoch
}

Next, the function where the above class is used. The following function is called directly from main() and passed a Policy object which is completely independent and separate from the Patient class:

接下来,使用上述类的函数。下面的函数直接从main()调用,并传递一个完全独立于Patient类的策略对象:

void simulate1(Policy& P)
{
    // ...
    Patient patient(260);

    for(int idx=0; idx<(P.size); idx++)
    {
        while(state != 9) // while patient not dead
        {
                // ...
                patient.recordPSA(age,PSA);
                // ...
                patient.recordPSA(age);
                // ...
                patient.recordBiopsy(age,biopsyResult);
                // ...
                patient.recordRP(age,true);
                // ...
                patient.recordRP(age,false);
                // ...

        } // end patient (while loop)

    } // end sample (for loop)

} // end function

3 个解决方案

#1


7  

You're violating the rule-of-three (or for C++11, the rule-of-five). You need a copy constructor and copy-assignment operator that does a deep copy of the pointer. Of course, since you don't track the size of the array you allocate, this isn't possible without introducing a second data member.

您违反了三规则(或者对于c++ 11,即五规则)。您需要一个复制构造函数和复制赋值操作符,该操作符会对指针进行深入的复制。当然,由于不跟踪所分配的数组的大小,因此不引入第二个数据成员是不可能的。

#2


2  

This doesn't answer your question directly, but also consider using std::vector.

这并不能直接回答您的问题,但也可以考虑使用std::vector。

#3


0  

There is nothing in any of the record... methods that bounds checks the age. So, if age happens to be greater than 260 or less than 0 in your example, you will write past the bounds of either RP or Biopsy or PSA. That leads directly to a "double free or corruption" error.

没有任何记录……界限检查年龄的方法。所以,如果你的例子中年龄大于260或小于0,你会写超过RP或活检或PSA的界限。这直接导致了“双重*或腐败”的错误。

#1


7  

You're violating the rule-of-three (or for C++11, the rule-of-five). You need a copy constructor and copy-assignment operator that does a deep copy of the pointer. Of course, since you don't track the size of the array you allocate, this isn't possible without introducing a second data member.

您违反了三规则(或者对于c++ 11,即五规则)。您需要一个复制构造函数和复制赋值操作符,该操作符会对指针进行深入的复制。当然,由于不跟踪所分配的数组的大小,因此不引入第二个数据成员是不可能的。

#2


2  

This doesn't answer your question directly, but also consider using std::vector.

这并不能直接回答您的问题,但也可以考虑使用std::vector。

#3


0  

There is nothing in any of the record... methods that bounds checks the age. So, if age happens to be greater than 260 or less than 0 in your example, you will write past the bounds of either RP or Biopsy or PSA. That leads directly to a "double free or corruption" error.

没有任何记录……界限检查年龄的方法。所以,如果你的例子中年龄大于260或小于0,你会写超过RP或活检或PSA的界限。这直接导致了“双重*或腐败”的错误。