munmap_chunk():C ++程序中的指针无效

时间:2015-12-10 17:30:54

标签: c++ matrix

我收到错误“munmap_chunk():指针无效”,我不知道为什么。使用MultipliedByMatrix方法时出现问题。它无法正确删除在此方法中创建的矩阵。

#include "matrix.h"

Matrix::Matrix(int matr_size) {
    size = matr_size;
    Matr = new int *[size];
    for(int i = 0; i < size; i++)
        Matr[i] = new int[size];

    for(int i = 0 ; i < size; i++)
        for(int j = 0; j < size; j++)
            Matr[i][j] = rand() % 100;
    std::cout << "New matrix is created" << std::endl;
}

Matrix::~Matrix() {
    for(int i = 0; i < size; i++)
        delete[] Matr[i];
    delete[] Matr;
    Matr = NULL;
    std::cout << "Matrix is deleted" << std::endl;
}

Matrix Matrix::MultipliedByMatrix(Matrix OtherMatr) {
    Matrix new_matr = Matrix(this->GetSize());
    int new_value;

    for(int i = 0 ; i < size; i++)
        for(int j = 0; j < size; j++) {
            new_value = 0;
            new_value += Matr[j][i] * OtherMatr.GetValue(i, j);
            new_matr.SetValue(i, j, new_value);
        }
    return new_matr;
}

int Matrix::GetSize() {
    return size;
}

int Matrix::GetValue(int i, int j) {
    return Matr[i][j];
}

void Matrix::SetValue(int i, int j, int value) {
    Matr[i][j] = value;
}

2 个答案:

答案 0 :(得分:1)

你自己写过Matrix课吗?如果是这样,我打赌问题是你没有副本或移动构造函数。如果是这样,编译器将为您生成一个。这将复制size和Matr 的值,但它不会创建指向数组的副本。当你写:

    return new_matr;

这会创建一个新矩阵(使用复制构造函数 - 只复制指针),然后调用new_matr的析构函数(删除指向的内存)。然后调用函数处理垃圾内存,当它试图最终删除结果时,所有地狱都会破坏

您还需要编写一个移动赋值运算符。

或者将Matr设为std::vector<int>(长度&#39;大小&#39;平方),然后写:

int Matrix::GetValue(int i, int j) {
    return Matr[i*size+j];
}

(和其他功能类似)。 std::vector有一个正确的副本和移动构造函数,以及正确的赋值行为 - 所以它一切正常。 (它也会快得多 - 你保存一个完整的指针间接。)

答案 1 :(得分:0)

这不是问题的分析性答案,而是解决(或更好地规避)问题的建议。

如果可以,请尽量避免自己处理内存。 (你很可能真的可以避免它。)

您可以在#34; 1D or 2D array, what's faster?&#34;问题上阅读我的答案。为了获得冗长的表达式,为什么使用你正在使用的那种内存布局可能是不可取的。 此外,您将找到一个(但尚未经过测试)如何在std::vector之上实现简单矩阵容器的示例。

您可以查看该方案,并尝试根据需要实施自己的方案。与您的实现相比,该设计具有以下几个优点:

  • 它是模板化的,因此可以与int以及许多其他类型一起使用。
  • 轻松实现对标准容器概念的符合。
  • 不需要析构函数/复制构造函数/移动构造函数或赋值运算符:std::vector正在处理资源并执行&#34;脏工作&#34;为你。

如果您仍想使用RAW-Pointer方法(出于学术目的或其他目的):

  1. 阅读What is meant by Resource Acquisition is Initialization (RAII)?并尝试了解答案。

  2. 正确阅读What is The Rule of Three?并确保您已实施(最好遵守RAII概念)这些功能:

    • 复制构造函数,
    • 析构函数,
    • 赋值运算符,如果需要,
    • 移动构造函数和
    • 移动赋值运算符。
  3. 仍然阅读我对&#34; 1D or 2D array, what's faster?&#34;的答案问题是如何组织您的分配以便在std::bad_alloc的情况下保持异常安全。
  4. 示例:您的构造函数更好一点&#39;方式:

    Matrix::Matrix(std::size_t const matr_size) // you have a size here, no sign required
    {
      Matr = new int*[matr_size];
      std::size_t allocs(0U);
      try
      { // try block doing further allocations
        for (std::size_t i = 0; i < matr_size; ++i)
        {
          Matr[i] = new int[matr_size]; // allocate
          ++allocs; // advance counter if no exception occured
          for(std::size_t j = 0; j < matr_size; j++)
          {
            Matr[i][j] = rand() % 100;
          }
        }
      }
      catch (std::bad_alloc & be)
      { // if an exception occurs we need to free out memory
        for (size_t i = 0; i < allocs; ++i) delete[] Matr[i]; // free all alloced rows
        delete[] Matr; // free Matr
        throw; // rethrow bad_alloc
      }
    }