0

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

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

*** 检测到 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;

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

4

3 回答 3

2

错误是您在分配的空间之外写:罪魁祸首是这一行

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 指针异常。

于 2012-11-27T00:58:27.377 回答
1

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

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

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

于 2012-11-27T00:52:29.373 回答
0

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

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

于 2012-11-27T00:55:00.463 回答