删除矢量元素指向的已分配内存会导致程序崩溃

Deleting allocated memory pointed by vector element crashes the program

本文关键字:内存 崩溃 程序 分配 元素 删除      更新时间:2023-10-16

我正在编写一个动态程序,该程序将读取Oracle数据库元数据并在内存中构建其结构。

当我释放创建为new的内存来保存Oracle发送给我的数据时,我遇到了一个问题。这个结构被放在一个向量中,运行良好(我可以读取和处理它)。

这是我的代码(数据库内容被删除是为了关注这个问题):

    struct OracleColumnStruct {
        std::string name;
        ub2 ociType;
        FieldType fieldType;
        int size;
        char *buffer;
        sb2  *indicator;
        OCIDefine *defineHandler;
    };
    std::vector<OracleColumnStruct> columns;
void AllocateColumns() 
{
        columnCount = ... // whatever from database
        for (unsigned int i = 0; i < columnCount; i++)
        {
            ociType = ... // whatever from database
            size = ... // whatever from database
            OracleColumnStruct data;
            data.name = "whatever";
            data.ociType = ociType;
            data.size = size;
            data.buffer = new char[size];
            data.indicator = new sb2;
            columns.push_back(data);
        }
}
void FreeColumns()
{
        for (auto &column : columns)
        {
            if (column.buffer)
                delete column.buffer; <<<- Crash here on 2nd interaction
            if (column.indicator)
                delete column.indicator;
        }
}

崩溃消息:

HEAP CORRUPTION DETECTED: after Normal block (#16497) at 0x00261940.
CRT detected that the application wrote to memory after end of heap buffer.

当我需要释放结构时,它会释放第一个元素,在第二次处理时,向量似乎会丢失。

删除指针引用会混淆整个向量吗?在这种情况下该怎么办?

buffer是用new[]分配的,因此必须使用delete[]而不是delete来释放它。

indicator是用new分配的,因此必须使用delete而不是delete[]来释放它。

不需要检查null,deletedelete[]已经为您处理了:

void FreeColumns()
{
    for (auto &column : columns)
    {
        delete[] column.buffer;
        delete column.indicator;
    }
}

也就是说,您应该使用std::vectorstd::unique_ptr,然后您可以完全摆脱FreeColumns(),并在需要时简单地调用columns.clear()

struct OracleColumnStruct {
    std::string name;
    ub2 ociType;
    FieldType fieldType;
    std::vector<char> buffer;
    std::unique_ptr<sb2> indicator;
    OCIDefine *defineHandler;
};
void AllocateColumns 
{
    columnCount = ... // whatever from database
    for (unsigned int i = 0; i < columnCount; i++)
    {
        ...
        OracleColumnStruct data;
        data.name = "whatever";
        data.ociType = ociType;
        data.buffer.resize(size);
        data.indicator.reset(new sb2);
        // or: data.indicator = std::make_unique<sb2>();
        columns.push_back(data);
       ...
    }
}

如果您已经在数组形式中分配了new

char* buffer = new char[size];

那么你应该使用delete的数组形式来删除

delete[] buffer;