删除自定义数组会导致堆错误

时间:2010-10-31 15:34:27

标签: c++ pointers

TL; DR

Boost-Test-Framework在传递所有测试并泄漏所有内存时没有发生错误而崩溃。

使用提到的析构函数实现多次测试失败。清除函数也会引发堆错误。

我们在dtor上做错了什么?

TL; DR

这与大学家庭作业有关,也是我朋友解决问题的方法。为了更多地使用C风格的指针和更低级的编程风格,我们需要实现自己的动态数组。

根据我们老师的900-LOC Boost-Test Framework,他的任务完整且功能齐全。唯一的问题是当测试退出或调用已实现的dtor时崩溃(或堆错误,因为没有弹出真正的错误消息)。

他的动态数组使用三个指针:pFirst, pLast and pEnd,指向数组的第一个元素,指向数组中最后一个元素的指针,并分别指向数组中最后一个尚未分配的元素

只要他没有尝试删除任何指针,他的程序就会通过。这是一个坏主意,但是嘿,它让他通过作业。现在。

我的朋友已多次尝试实现析构函数,但它们都会导致堆错误并导致测试框架失败。

// Teacher's recommended dtor.
Field::~Field()
{
    for(int i(0); i != this->size(); ++i)
        (pFirst+i)->~T();
    delete pFirst;
    pFirst = pLast = pEnd = NULL;
}

// My recommendation to friend.
Field::~Field()
{
    delete[] pFirst;
    pFirst = pLast = pEnd = NULL;
}

都崩溃了同样的堆错误。

Assertion failed: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

典型的测试链如下:

BOOST_AUTO_TEST_CASE( TEST_clear )
{
    Field f( 3, 4.0f );
    f.clear();  // Error here IF we use delete in the clear method.
    BOOST_CHECK( f.size()==0 );
    BOOST_CHECK( f.capacity()==4 ); 
} // Error here; during destruction IF we have implemented the dtor.

当我们尝试替换数组时,clear方法会发出相同的错误,所以我们只有:

void Field::clear()
{
    size_t capa = capacity();
    T *temp =pFirst;
    pFirst = new T[capa];
    pLast = pFirst;
    pEnd = pFirst+capa;
}

在处理删除指针时,我们对dtor做了什么错误,明确和一般?

2 个答案:

答案 0 :(得分:3)

Assertion failed: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)表示堆损坏。通常在写入已分配内存的末尾时发生。 我在您的代码中看到以下问题:在Field::clear中,您将指针存储在pFirst中的已分配内存中,并立即用pLast覆盖它。我认为您应该将其更改为pLast = pFirst;

老师推荐的dtor对我没用。如果您使用new[]进行分配,然后使用delete[]取消分配,请不要单独调用每个析构函数并使用delete

答案 1 :(得分:2)

如果pFirst指向数组的第一个元素,那么您的“老师建议的dtor”就错了。你需要说delete[] pFirst来解除分配数组。

但是有许多问题可能导致这种情况,例如由其他一些函数引起的堆损坏。尝试在内存损坏检查程序(如Valgrind)中运行它,以查看是否溢出了堆缓冲区。

相关问题