我有一个动态重新分配大小的矩阵类。具体而言:动态重新分配行数组。
但是在某些情况下,当调用矩阵的析构函数时会出现内存释放问题:
*** glibc检测到*** ./solver:free():下一个大小无效(快):0x0000000000c112b0 ***
并且该过程正在中止。
Matrix类:
#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;
所以我不知道会出现什么问题。有什么建议吗?
答案 0 :(得分:2)
错误是你在分配的空间之外写的: 罪魁祸首就是这条线
Row **newData = new Row *[size];
if (data != NULL)
memcpy(newData, data, sz * sizeof(Row*));
如果sz大于大小,那么你会写得太多而且可能会破坏你的堆。将其更改为下面的代码,一切都应该更好。这样,您将始终复制有效数据,并且不会超过您分配的数据。
Row **newData = new Row *[size];
if (data != NULL)
memcpy(newData, data, (size>sz?sz:size) * sizeof(Row*));
调整从3到2的工作是运气(以及堆如何工作)。
此外,您不检查新的Row []是否失败,但这会导致NULL指针异常。
答案 1 :(得分:1)
经过粗略的考试后,我打赌你的问题是:
if (data != NULL)
memcpy(newData, data, sz * sizeof(Row*));
如果你从10缩小到7,那么你只需要在一个大小为7的缓冲区上复制10个指针。
答案 2 :(得分:0)
当您分配一些内存并写入该内存的末尾,覆盖您不拥有的用于管理空闲堆的内存时,就会发生这种情况。
查看您写入已分配内存的每个位置。确保您没有写过所请求的内存的末尾并且正确拥有。