【问题标题】:munmap_chunk(): invalid pointer in C++ programmunmap_chunk():C++ 程序中的无效指针
【发布时间】:2016-03-16 11:03:17
【问题描述】:

我得到一个错误“munmap_chunk(): invalid pointer”,我不知道为什么。当我使用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;
}

【问题讨论】:

  • 您可能会在这里找到帮助:stackoverflow.com/questions/6199729/…
  • @nos 不,我没有。那我应该在哪里使用呢?
  • 我认为您需要一个复制构造函数来复制 Matr 数组。默认的复制构造函数只会复制 Matr 指针,当临时的 new_matr 被销毁时,该指针变得无效。
  • 如果MultipliedByMatrix 返回Matrix* 会更简单、更高效。它可以使用Matrix *new_matr = new Matrix(this-&gt;GetSize()) 分配它并返回该指针,而无需复制所有内容。
  • 要将您的示例代码变成MCVE,您需要将matrix.h 和合适的main() 内联到您的代码中。然后人们将能够编译和运行(确保它可以自行构建 - 您需要至少包含一个标准头文件)。当您有一个演示问题的最小独立程序时,请编辑您的帖子。

标签: c++ matrix


【解决方案1】:

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

如果可以,请避免自行处理内存。 (而且很有可能你实际上可以避免它。)

您可以阅读我对“1D or 2D array, what's faster?”问题的回答,详细了解为什么可能不希望使用您正在使用的内存布局。 此外,您将找到一个(尚未测试的)示例,说明如何在 std::vector 之上实现一个简单的矩阵容器。

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

  • 它是模板化的,因此可用于int 以及许多其他类型。
  • 与标准容器概念的一致性很容易实现。
  • 不需要析构函数/复制构造函数/移动构造函数或赋值运算符:std::vector 正在处理资源并为您完成“脏活”。

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

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

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

    • 复制构造函数,
    • 析构函数,
    • 赋值运算符,如果需要
    • 移动构造函数和
    • 移动赋值运算符。
  3. 仍然阅读我对“1D or 2D array, what's faster?”问题的回答,了解您希望如何组织分配,以便在出现std::bad_alloc 时确保异常安全。

示例:您的构造函数采用“更好一点”的方式:

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
  }
}

【讨论】:

    【解决方案2】:

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

        return new_matr;
    

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

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

    或者将 Matr 设为 std::vector&lt;int&gt;(长度为“大小”的平方),然后写:

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

    (对于其他功能也是如此)。 std::vector 有一个正确的复制和移动构造函数,以及正确的赋值行为——所以一切都会正常工作。 (它也会快很多 - 你保存了整个指针间接。)

    【讨论】:

    • 谢谢你的回答,我写了一个复制构造函数,它工作了
    猜你喜欢
    • 1970-01-01
    • 2018-08-23
    • 2020-08-04
    • 2016-08-08
    • 2014-05-14
    • 2011-09-06
    • 2020-08-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多