【问题标题】:munmap_chunk invalid pointer when operator and then destroctor calledmunmap_chunk 运算符和析构函数调用时指针无效
【发布时间】:2014-12-11 09:30:30
【问题描述】:

我在编写 C++ 代码时遇到了一个奇怪的情况。在我的代码中,我有一个名为C 的矩阵对象。 C 将等于矩阵 AB 的总和。 A+B 的值是通过operator+ 计算得出的。当C的生命结束时,我面对的是invalid pointer error

这是我的完整代码:

#include <iostream>
#include <vector>
using namespace std;

class CMatrix
{
private:
    int rows=0,columns=0;
    int **members=NULL;
    void allocate(int rows,int columns);
public:
    CMatrix(int rows,int columns);
    CMatrix(int rows,int columns,vector<vector<int>> clone);
    CMatrix(const CMatrix& clone);
    ~CMatrix();
    void print();
    void sum(const CMatrix &A,const CMatrix &B);
    CMatrix operator+(const CMatrix &B);
};

void CMatrix::allocate(int rows,int columns)
{
    this->rows=rows;
    this->columns=columns;
    members=new int*[rows];
    for(int i=0;i<columns;i++)
        members[i]=new int[columns];
}

CMatrix::CMatrix(const CMatrix& clone)
{
    allocate(clone.rows,clone.columns);
    for(int i=0;i<rows;i++)
        for(int j=0;j<columns;j++)
            members[i][j]=clone.members[i][j];
}

CMatrix::CMatrix(int rows,int columns)
{
    allocate(rows,columns);
}

CMatrix::CMatrix(int rows,int columns,vector<vector<int>> clone)
{
    allocate(rows,columns);
    for(int i=0;i<rows;i++)
        for(int j=0;j<columns;j++)
            members[i][j]=clone[i][j];
}

CMatrix::~CMatrix()
{
    for(int i=0;i<rows;i++)
        delete [] members[i];
    delete [] members;
}

void CMatrix::print()
{
    cout<<"["<<endl;
    for(int i=0;i<rows;i++)
    {
        for(int j=0;j<columns;j++)
            cout<<members[i][j]<<(j==columns-1?"":",\t");
        cout<<endl;
    }
    cout<<"]"<<endl;
}

void CMatrix::sum(const CMatrix &A,const CMatrix &B)
{
    // at this point, all matrices must have the same dimention
    for(int i=0;i<rows;i++)
        for(int j=0;j<columns;j++)
            members[i][j]=A.members[i][j]+B.members[i][j];
}

CMatrix CMatrix::operator+(const CMatrix &B)
{
    CMatrix result(rows,columns);
    result.sum(*this,B);
    return result;
}

int main()
{
    CMatrix A(3,3,{{1,2,3},{4,5,6},{7,8,9}});
    CMatrix B(3,3,{{3,4,-1},{7,-2,1},{3,2,-4}});
    CMatrix C(3,3);
    cout<<"A is:"<<endl;
    A.print();
    cout<<"B is:"<<endl;
    B.print();
    cout<<"C=A+B is:"<<endl;
    C=A+B;
    C.print();
    return 0;
}

当我运行我的代码时,我遇到了错误的结果和无效的指针错误:

A is:
[
1,  2,  3
4,  5,  6
7,  8,  9
]
B is:
[
3,  4,  -1
7,  -2, 1
3,  2,  -4
]
C=A+B is:
[
0,  0,  33
17019120,   0,  7
17019408,   0,  5
]
*** Error in `./a.out': munmap_chunk(): invalid pointer: 0x000000000103b230 ***
Aborted (core dumped)

如何解决?

我再次使用 valgrind 运行程序:

$ valgrind --tool=memcheck --db-attach=yes ./a.out
==11847== Memcheck, a memory error detector
==11847== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==11847== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==11847== Command: ./a.out
==11847== 
A is:
[
1,  2,  3
4,  5,  6
7,  8,  9
]
B is:
[
3,  4,  -1
7,  -2, 1
3,  2,  -4
]
C=A+B is:
[
==11847== Invalid read of size 8
==11847==    at 0x400FEE: CMatrix::print() (test.cpp:64)
==11847==    by 0x401655: main (test.cpp:96)
==11847==  Address 0x5a1d910 is 0 bytes inside a block of size 24 free'd
==11847==    at 0x4C2C83C: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11847==    by 0x400F7D: CMatrix::~CMatrix() (test.cpp:55)
==11847==    by 0x401646: main (test.cpp:95)
==11847== 
==11847== 
==11847== ---- Attach to debugger ? --- [Return/N/n/Y/y/C/c] ---- 

似乎 NRVO 没有正确实施!怎么办?

注意:我编译时使用:g++ -g -std=c++11 test.cpp

编辑:

添加这部分代码可以解决问题,但会给我的程序增加负担。如何享受 NRVO 的优势?

void CMatrix::operator=(const CMatrix &B)
{
    for(int i=0;i<rows;i++)
        for(int j=0;j<columns;j++)
            members[i][j]=B.members[i][j];
}

【问题讨论】:

  • @PiotrS。我曾假设 NRVO 已应用于我的代码

标签: c++ pointers operator-overloading destructor rvo


【解决方案1】:

首先,你的'allocate()' 中有一个错误:你应该检查'i

 CMatrix D=A+B

而不是

 C=A+B. 

如果您向构造函数/析构函数添加一些日志记录,您将看到优化执行得非常完美。 C 是早先用其他参数创建的,它不能被另一个没有复制构造函数的对象初始化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-04
    • 2018-08-23
    • 2012-07-19
    • 1970-01-01
    • 2020-09-05
    • 1970-01-01
    • 2016-08-08
    • 2014-05-14
    相关资源
    最近更新 更多