2012-11-27 60 views
0

我有一个矩阵类动态重新分配大小。具体来说:动态重新分配一行数组。释放内存失败:free():无效下一个大小(快):

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

*** glibc的检测*** ./solver:免费():无效的下一个尺寸(快):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; 
} 

所以,这是代码。当我制作一个矩阵并稍后减小它的大小并调用destrtructor时,问题就出现了。例如:

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; 

所以我不知道有什么可以是错误的。有什么建议么?

回答

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

+0

这是有效的!非常感谢你。我没有注意到这一点。 但是为什么释放有问题?我看不到任何联系。 你是否建议检查新的失败总是如何? :D – pablo

+0

堆将在您分配内存时存储一些信息,如果您在给定的区域之外写入,则会覆盖堆释放缓冲区所需的信息。对于另一个问题,只需检查它是否newData [i] == NULL,如果它是(并释放任何分配的内存)则返回一个错误。 – Gille

1

一个非常粗略的检查后,我敢打赌,你的问题是这样的:

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

如果你从萎缩,比如说10至7日,您刚才复制10个球能对其加以大小的缓冲区7.

0

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

查看您写入分配内存的每个地方。确保你不会写出超出你请求和合理拥有的内存的结尾。

相关问题