删除[]导致C 中的崩溃

Delete[] causing crash in C++

本文关键字:崩溃 导致 删除      更新时间:2023-10-16

我正在使用我以前的帖子中的此代码中的相同代码工作,但我已经做了多个更改。我的问题是我有一个动态数组,在操作员内部的copy构造器内部的 delete[]中,我在下面的错误中获得了错误。

lab3.exe中的0x0f7063bb(ucrtbased.dll)抛出的例外

如果有此例外的处理程序,则可以安全地继续该程序。

谁能帮我理解为什么?我检查了相关的问题,但是与我看到的相关的错误不同,但我在Google搜索中没有找到结果。我在Visual Studio 2015上使用C 11。

#include "ListArray.h"
template < typename DataType >
List<DataType>::List ( int maxNumber )
{
    //maxSize = MAX_LIST_SIZE; maybe???
    maxSize = maxNumber;
    dataItems = new DataType[maxSize];
    size = maxSize - 1;
    cursor = 0; // sets cursor to the first value in list
    for (; cursor <= size; cursor++)
        dataItems[cursor] = 1;
    cursor = 0;
}
template < typename DataType >
List<DataType>::List ( const List& source )
{
    *this = source; // should be handled by copy constructor
}
template < typename DataType >
List<DataType>& List<DataType>::operator= ( const List& source )
{
    if (this != &source)
    {
        maxSize = source.maxSize;
        size = source.size;
        cursor = source.cursor;
        delete []dataItems; // clears dataItems, weird run-time error here. Why? 
        dataItems = new DataType[size];
        for (int count = 0; count < size; count++)
            dataItems[count] = source.dataItems[count];
    }
    else
        // do nothing, they are the same so no copy is made
        return *this;
}
template < typename DataType >
List<DataType>::~List ()
{
    maxSize = 0;
    size = 0;
    cursor = -1;
    delete[] dataItems;
}

编辑:我最初发布了其他几个不完整功能,也是我要构建的程序的一部分。我的意思是只包括我所知道的正在引起的问题。我对糟糕的帖子表示歉意。

如果您要使用分配操作员制作副本,则需要一个空的对象才能开始,否则operator=在尝试清理旧内容时会发生可怕的失败替换它们(正如Sam在他的回答中所解释的那样,Mikecat在他的评论中提到的 - 给了他们upvotes-以及迪特在您之前的问题上告诉您的)。

由于C 11,构造函数链接又称构造函数委托是可以的,因此:

template < typename DataType >
List<DataType>::List ( const List& source )
    : List() /* default construct object before proceeding */
{
    *this = source; // should be handled by copy constructor
}

另一个选项是使复制构造函数负责创建默认对象本身,这就是C 98和C 03中所需的内容:

template < typename DataType >
List<DataType>::List ( const List& source )
    : maxSize(0), dataItems(NULL), size(0) // initialize members
{
    *this = source; // should be handled by copy constructor
}

,但这正在重复默认构造函数的功能,因此,只要您的编译器支持C 11功能,就可以调用现有的功能。

构造委员会委托的细节...变得复杂。除其他外,通常从对象构造函数内部抛出的任何例外都可以防止对象存在,并且destructor均未调用。当使用委托时,当任何构造函数完成时,对象就会生存,并且包装器构造函数中的例外将面对一个已经活着的对象,并为您调用破坏者。这种行为可能是理想的,也可能不是可取的,但这是值得关注的,因为异常安全在现代C 很重要。

复制构造器不会在类的新实例中初始化任何内容。它所做的就是调用分配操作员。

分配操作员执行:

delete []dataItems;

由于dataItems尚未初始化,因此导致不确定的行为和立即崩溃。