【问题标题】:Freeing memory failure: free(): invalid next size (fast): [duplicate]释放内存失败:free():下一个大小无效(快速):[重复]
【发布时间】:2012-11-14 13:44:16
【问题描述】:

我有一个动态重新分配大小的矩阵类。具体来说:动态重新分配行数组。

但在某些情况下,调用矩阵的析构函数时会出现内存释放问题:

*** 检测到 glibc *** ./solver: free(): invalid next size (fast): 0x0000000000c112b0 ***

并且进程正在中止。

矩阵类:

#ifndef __matrix_hpp
#define __matrix_hpp

#include <cstring>
#include <stdexcept>
#include "row.hpp"

using namespace std;

class Matrix {

public:
    Matrix();
    ~Matrix();
    size_t size();
    void resize(size_t size);
    double get(size_t x, size_t y) throw (out_of_range);
    void set(size_t x, size_t y, double value) throw (out_of_range);
    double getfv(size_t y) throw (out_of_range);
    void setfv(size_t y, double value) throw (out_of_range);
    void optimize(size_t y) throw (out_of_range);
    void _print();

private:
    size_t sz;
    Row **data;

};

#endif

以及重要功能的主体:

Matrix::~Matrix() {
    if (data != NULL) {
        for (size_t i = 0; i < sz; ++i)
            delete data[i];
        delete [] data;
    }
}

void Matrix::resize(size_t size) {
    if (size == sz)
        return;
    Row **newData = new Row *[size];
    if (data != NULL)
        memcpy(newData, data, sz * sizeof(Row*));
    if (size > sz) {
        for (size_t i = sz; i < size; ++i)
            newData[i] = new Row();
    }
    else {
        for (size_t i = size; i < sz; ++i)
            delete data[i];
    }
    delete [] data;
    data = newData;
    sz = size;
}

所以,这就是代码。当我制作一个矩阵然后减小它的大小并调用析构函数时,问题就来了。例如:

Matrix *matrix = new Matrix();
matrix->resize(10);
matrix->resize(7);
delete matrix;

但是让矩阵变大效果很好:

Matrix *matrix = new Matrix();
matrix->resize(10);
matrix->resize(13);
delete matrix;

最有趣的是,这个例子有效:

Matrix *matrix = new Matrix();
matrix->resize(3);
matrix->resize(2);
delete matrix;

所以我不知道有什么问题。有什么建议吗?

【问题讨论】:

    标签: c++ debugging memory free allocation


    【解决方案1】:

    错误是您在分配的空间之外写入: 罪魁祸首就是这条线

    Row **newData = new Row *[size];
    if (data != NULL)
        memcpy(newData, data, sz * sizeof(Row*));
    

    如果 sz 大于 size,那么你会写太多并且可能会破坏你的堆。将其更改为下面的代码,一切应该会更好。这样,您将始终复制有效数据,并且不会超过您分配的数据。

    Row **newData = new Row *[size];
    if (data != NULL)
        memcpy(newData, data, (size>sz?sz:size) * sizeof(Row*));
    

    将大小从 3 调整为 2 取决于运气(以及堆的工作方式)。

    此外,您不会检查 new Row[] 是否失败,但这会导致 NULL 指针异常。

    【讨论】:

    • 行得通!非常感谢。我没有注意到这一点。但是为什么释放会有问题呢?我看没有联系。您是否建议检查 new 是否总是失败? :D
    • 堆将在您分配它时获得的内存周围存储一些信息,如果您在分配给您的区域之外写入,您将覆盖堆释放缓冲区所需的信息。对于另一个问题,只需检查它是否 newData[i] == NULL,如果是则返回错误(并释放任何分配的内存)。
    【解决方案2】:

    经过非常粗略的检查,我敢打赌你的问题是:

    if (data != NULL)
        memcpy(newData, data, sz * sizeof(Row*));
    

    如果您从 10 缩小到 7,您只需将 10 个指针复制到大小为 7 的缓冲区上。

    【讨论】:

      【解决方案3】:

      当您分配一些内存并写入超过该内存的末尾时会发生这种情况,覆盖您不拥有的用于管理空闲堆的内存。

      查看您写入分配内存的每个位置。确保您不会写超出您请求并合法拥有的内存的末尾。

      【讨论】:

        猜你喜欢
        • 2012-05-22
        • 2012-10-25
        • 2013-02-05
        • 1970-01-01
        • 2017-03-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-23
        相关资源
        最近更新 更多