0

I defined my matrix class and I put here the simplifed version:

// matrix of double type
typedef std::vector< std::vector< double > > dbmatrix; 

class MMatrix
{
private:
    // matrix with size of rowsNum times colsNum
    size_t rowsNum; // number of rows
    size_t colsNum; // number of columns

protected:
    dbmatrix mMat; // the matrix

public:
    // Constructor
    MMatrix(size_t m, size_t n, double initVal); 

...

    //  Display matrix in console (unsuitable for large matrix)
    void display(void);
};

// initialize a m-by-n matrix with an initial Value
MMatrix::MMatrix(size_t m, size_t n, double initVal)
{
    this->rowsNum = m;
    this->colsNum = n;

    this->mMat.reserve(this->rowsNum);

    for (uint i = 0; i < this->rowsNum; i++)
    {
        dbvector oneRow(this->colsNum, initVal);
        this->mMat.push_back(oneRow);
    }
}

// Display matrix in console
void MMatrix::display()
{
    for (uint i = 0; i < rowsNum; i++)
    {
        for (uint j = 0; j < colsNum; j++)
        {
            std::cout << mMat[i][j] << " ";
        }
        std::cout << std::endl;
    }
    std::cout << std::endl;
}

Then I generated a 2 dimensional pointer to receive the result from the function "matrixDiff"

MMatrix** divH = matrixDiff(*V, fwdKer, false);

The weird thing happened when I tried the following code after it:

(*divH[0]).display();
(*divH[0]).display();

before I executed the first line, my object pointer looks normal (fig1) fig1.pointer to a 10-by-10 matrix looks normal The first line successfully give the wanted result.

However, after execute the first line, the second line (which is exactly the same) throw a Access violation. The debugger indicates the pointer lost its target after executing the first line (fig2) fig2. pointer lost its target.

In additional test, I tried:

divH[0]->display();
divH[0]->display();

Which is still not working. However, when I tried the following code:

MMatrix* testMat = divH[0];
testMat->display();
testMat->display();

It works perfectly, which completely make me confused.

What's more, I also tried to display the matrix inside the function "matrixDiff" I create:

MMatrix** matrixDiff(MMatrix depthMat, MMatrix ker, bool isDirect)
{
    MMatrix* retMat[3];

    retMat[0] = filter(depthMat, ker);
    retMat[1] = filter(depthMat, (~ker));


...

    retMat[0] -> display();
    retMat[1] -> display();

    retMat[2] = diffMag; // gradient magnitude

    return retMat;
}

With the same two-line commands, it works either!

So, I am super confused now about c++ pointers. It seems that passing result through object pointers will change something, though I originally thought it only pass the address of the object. Could you point out what the real problem is here? Thank you!

Maxwell
  • 1
  • 1

1 Answers1

2

You return a pointer to a local variable. The variable retMat is local, and will go out of scope once the function returns, leaving you with a stray pointer and using that pointer will lead to undefined behavior.

I recommend you use an std::array instead:

std::array<3, MMatrix*> retMat;

On an unrelated note, you should probably learn about passing objects by reference instead of by value. If depthMat or ker are large, you will have a lot of data to copy each call you make. If you don't modify them consider using constant references.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Thanks for you suggestions, it helps a lot. Can I know why using "std::array<3, MMatrix*> retMat;" works? Isn't it still returning "an array of 3 pointers pointing to the local variables?". To avoid reference to local variable, should I return the matrix by input argument like "void matrixDiff( MMatrix** retMat , ...)"? Thanks! – Maxwell Jan 12 '16 at 06:54
  • 1
    @Maxwell When you return a `std::array` object, you actually return an *object* which have functions for copying and moving. When you return a C-style array, you return a pointer to an array that goes out of scope. – Some programmer dude Jan 12 '16 at 06:57