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

时间:2016-04-19 22:58:40

标签: c++ vector

我正在编写一个动态程序,它将读取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.

当我需要释放结构时,它释放第一个元素,在第二个处理中,矢量变为迷失。

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

2 个答案:

答案 0 :(得分:1)

如果你已经以数组形式分配了一些新东西

char* buffer = new char[size];

然后你应该使用删除的数组形式进行删除

delete[] buffer;

答案 1 :(得分:1)

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

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

并且无需检查空值,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);
       ...
    }
}