c++pointersstackpointer-arithmeticstack-corruption

Memory hack to transpose matrix corrupts stack, C++


I need to implement a matrix transpose procedure in C++. The problem is the signature, the function has to be called like this:

transpose(in_mat[0][0], n, m, out_mat[0][0])

where n and m are the dimensions. All values are doubles, both the matrices and the dimensions.

Since the code is automatically generated, I can't fix this.

My workaround looks like this:

void transpose(double& in_mat, const double _n, const double _m, double& out_mat)
{
    int n = _n, m = _m;
    double* in_pointer= &in_mat;
    double* out_pointer= &out_mat;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            *(out_pointer+(j*n+i)) = *(in_pointer+(i*m + j));
        }
    }
}

It works fine. I've constructed a test case with two matrices of different width and height. One is filled with random numbers, the other is filled with zeros. Then the transpose procedure is called and the two matrices are compared. The functionality is correct.

But it corrupts the stack. When run in Visual Studio 2015 there is a warning

Run-Time Check Failure #2 - Stack around the variable 'in_mat' was corrupted.

What did I do wrong ? Why is the stack corrupted ? Code after the invocation of transpose works correctly.

EDIT:

Here is the complete setup:

#include <random>
#include <iostream>

void transpose(double& in_mat, const double _n, const double _m, double& out_mat)
{
    int n = _n, m = _m;
    double* in_pointer = &in_mat;
    double* out_pointer = &out_mat;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            *(out_pointer+(j*n+i)) = *(in_pointer+(i*m + j));
        }
    }
}


int main()
{

    double in_mat[5][4];
    double out_mat[4][5];// assign matrix

    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 5; j++) {
            in_mat[i][j] = std::rand();
            out_mat[j][i] = 0;
        }
    }

    double n = 5;
    double m = 4;

    transpose(in_mat[0][0], n, m, out_mat[0][0]);

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (in_mat[i][j] - out_mat[j][i]>0.0001) {
                std::cout << "code is broken" << std::endl; //never reached
            }
        }
    }
    std::cout << "finished" << std::endl;
}

Solution

  • Your subscripts (or loop limits) were backwards where you initialized the matrices.

    You have

    double in_mat[5][4];
    double out_mat[4][5];// assign matrix
    
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 5; j++) {
            in_mat[i][j] = std::rand();
            out_mat[j][i] = 0;
        }
    }
    

    When j==4 you are writing beyond the end of out_mat