Click here to Skip to main content
15,306,142 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
I've written a code to calculate the invert of an array in c#. Now I've converted it to c++, but when I run, it shows "Unhandled exception at 0x004011a0 in math.exe: 0xC0000005: Access violation reading location 0xabababb3" message and it exits the program. I think it's about pointers i used as 2D arrays. in my main function I call the Invert function with a 2D pointer parameter. Please help.

Code:

C#
CDoubleMatrix::CDoubleMatrix(int row,int col)
{
    this->row=row;
    this->col=col;
}

void CDoubleMatrix::makeResult()
{
    result=new double*[row];
    for (int i=0;i<row;i++)
        result[i]=new double[col];
}

double** CDoubleMatrix::DevideByConst(double** mtx, double val)
{
    makeResult();

    for (int i=0;i<row;i++)
    {
        for (int j=0;j<col;j++)
        {
            result[i][j]=mtx[i][j]/val;
        }
    }
    return result;
}

double** CDoubleMatrix::Invert(double** mtx)
{
    if (Determinant(mtx) == 0)
    {

    }
    if (row == 2 && col == 2)
    {
        double** tempMtx=new double*[2];
        for (int i=0;i<2;i++)
            tempMtx[i]=new double[2];

        tempMtx[0][0] = mtx[1][1];
        tempMtx[0][1] = -mtx[0][1];
        tempMtx[1][0] = -mtx[1][0];
        tempMtx[1][1] = mtx[0][0];

        return DevideByConst(tempMtx, Determinant(mtx));
    }
    return DevideByConst(Adjoint(mtx), Determinant(mtx));
}

double CDoubleMatrix::Determinant(double** mtx)
{
    double determinent = 0;

    if (row != col)
    {

    }
    if (row == 1 && col == 1)
    {
    return mtx[0][0];
    }
    if (row == 2 && col == 2)
    {
        determinent = (mtx[0][0]* mtx[1][1])- (mtx[0][1]* mtx[1][0]);
        return determinent;
    }

    double** tempMtx=new double*[row-1];
    for (int i=0;i<row-1;i++)
        tempMtx[i]=new double[col-1];

    for (int j = 0; j < col; j++)
    {
        tempMtx = Minor(mtx, 0, j);
        determinent += pow((double)-1, (double)j)*(mtx[0][j]* Determinant(tempMtx));
    }

    return determinent;
}

double** CDoubleMatrix::Minor(double **mtx, int row, int column)
{
    if (this->row < 2 || this->col < 2)
    {

    }

    int i, j = 0;

    double** minorMtx=new double*[this->row-1];
    for (int i=0;i<this->row-1;i++)
        minorMtx[i]=new double[this->col-1];

    for (int k = 0; k < this->row - 1; k++)
    {
        if (k >= row)
            i = k + 1;
        else
            i = k;

        for (int l = 0; l < this->col - 1; l++)
        {
            if (l >= column)
                j = l + 1;
            else
                j = l;

            minorMtx[k][l] = mtx[i][j];
        }
    }
    return minorMtx;
}

double** CDoubleMatrix::Adjoint(double** mtx)
{
    if (row < 2 || col < 2)
    {

    }

    double** tempMtx=new double*[row-1];
    for (int i=0;i<row-1;i++)
        tempMtx[i]=new double[col-1];

    double** adjMtx=new double*[row];
    for (int i=0;i<row;i++)
        adjMtx[i]=new double[col];

    for (int i=0;i<row;i++)
    {
        for (int j=0;j<col;j++)
        {
            tempMtx = Minor(mtx, i, j);
            adjMtx[j][i] = pow((double)-1, (double)(i + j)) * Determinant(tempMtx);
        }
    }
    return adjMtx;
}


Update
In main function:

C#
double** r=new double*[10];
for (int i=0;i<10;i++)
    r[i]=new double[10];

double** m=new double*[10];
for (int i=0;i<10;i++)
    m[i]=new double[10];

for (int i=0;i<10;i++)
    for (int j=0;j<10;j++)
    m[i][j]=2;


CDoubleMatrix dm(10,10);

r=dm.Invert(m);

for (int i=0;i<10;i++)
    for (int j=0;j<10;j++)
        cout<<r[i][j]<<endl;
Posted
Updated 27-Oct-12 10:48am
v2
Comments
Richard MacCutchan 27-Oct-12 4:43am
   
Well we cannot guess where the problem is occurring or what the array indices may be at that point. Use your debugger to find out whare it is going wrong and why.
mehdi_k 27-Oct-12 4:56am
   
THAT is the problem, I can not debug it because when I use put breakpoint in anywhere in my code it just skips and ends the program!!!!
Richard MacCutchan 27-Oct-12 5:09am
   
Don't use breakpoints, step into the code one line at a time until you find out what is going wrong. There is no way we can guess what is happening.
mehdi_k 27-Oct-12 6:06am
   
when I step into, it goes to disassembly file!
I don't understand it.
Richard MacCutchan 27-Oct-12 9:01am
   
I have no idea what you may be doing, you need to try and give clearer information.
Santhosh G_ 27-Oct-12 4:51am
   
What is the implementation of makeResult() ?
Please attach to a debugger and find which function creates the access violation
mehdi_k 27-Oct-12 4:58am
   
makeResult() just creates a universal 2D pointer array named Result.

You defined your DoubleMatrix, but didn't initialize it ( I assume that is what the function DoubleMatrix::MakeResult() is for). As a result, your member variable DoubleMatrix::result is undefined,. It may be a non-null value, so if you acces it you may get an access violation.

[edit]checking your code I didn't see you accessing result unto the point you reported the exception, so it has to be something else.[/edit]

[edit2]
Ok, looking at your code, what it does is this:

1. It allocates a 10x10 matrix r and another 10x10 matrix m.
2. It initalizes all the coefficients of m to 2 (which means the determinant will be 0 btw)
3. It creates an object of type CDoubleMatrix, with its member variables set to row=col=10 and result=undefined
4. On this new object, you pass m to the function Invert(), which passes it on to Determinant()
5. After some checks, you allocate a new 9x9 matrix tempMtx
6. then you run a loop where you reassign tempMtx 10 times, creating 10 (memory-)leaking matrices! However, memory leaks don't cause run-time exceptions. To re-assign tempMtx, you call Minor(), then recursively call Determinant() again.
6.1 in Minor(), you allocate a 9x9 matrix, and (correctly?) copy a 9x9 submatrix for calculating the determinant into it.
6.2 in Determinant() you again create a 9x9 tempMtx (see step 5), then run a loop re-assigning it to whatever you would get from your looped call to Minor(), if it would return (see step 6 and 6.1):
7. The recursive call to Minor() again allocates a 9x9 matrix (should be 8x8 this time!), then attempts to copy a submatrix from the passed mtx, assuming that it is of the dimension 10x10. Unfortunately, it is 9x9 however, so you get memory access exceptions instead!
[/edit2]
   
v3
Comments
Richard MacCutchan 29-Oct-12 13:18pm
   
A brilliant analysis; I tried to chase this down but just got totally confused in the matrix copying code.
Stefan_Lang 30-Oct-12 4:44am
   
Thank you. Actually, I based this on your own response: it was on the right track and gave me a good starting point where to focus. I just couldn't decide where and why the dimensions were wrong, so I just followed the chain of execution.

Also, being a mathematician and intimately familiar with algebra (and its implementation) helps. ;-)
Richard MacCutchan 30-Oct-12 6:17am
   
Finding the problem is one thing, but explaining it as you have done is the really useful bit of your answer. My problem is that I still don't really understand more than the very basics of matrices, so when I look at something like this I have one picture missing from my brain.
[no name] 30-Oct-12 1:41am
   
You are right :)
Take a look at your code:
result[i][j]=mtx[i][j]/val;
where mtx comes as:
double** mtx
the compiler dont know the row dimensions of the 2-dimensional array.
therefore you should use a typedeclaration for the double array. so the compiler can see the dimensions of mtx parameter.
typedef double MAT3x3[3][3];
so you can call:
DevideByConst(MAT3x3& mtx, double val)
Best regards.
   
v2
Comments
mehdi_k 27-Oct-12 16:49pm
   
I've updated my question.
mbue 28-Oct-12 17:05pm
   
Your problem is the function Minor produces a matrix with smaller dimensions and calls the function Determinant always with the same dimensions.
The best way is to encapsulate the array into a class. Or you call all functions with matrix parameter with corresponding dimensions.
The exception is thrown because of invalid dimensions (this->row and this->col) are always the same but dimensions are changing.
Your code:
double** tempMtx=new double*[rows-1];
for (int i=0;i<rows-1;i++)
tempMtx[i]=new double[cols-1];

Best regards.
mehdi_k 29-Oct-12 4:13am
   
thank you mbue, I come up with same thing.
This is guesswork, but may be what the problem is.

The one piece of information that you have not given us is the parameter that you are using to call the Invert() function in the first place. My suspicion is that you are using a static array defined something like:
C++
double matrix[2][2] =
{
    { 2.0, 3.0 },
    { 4.0, 6.0 },
};
double** result = Invert(double**)matrix);

But in this case matrix[0] and matrix[1] are not pointers to arrays of doubles, but actual arrays. So, when Invert() (or any other function) tries to use what it thinks is the pointer, it causes an access error because the content is invalid.
   
Comments
mehdi_k 27-Oct-12 16:49pm
   
I've updated my question.
Richard MacCutchan 28-Oct-12 8:01am
   
Well I have run your code through the debugger and the best I can come up with is that your row count in CDoubleMatrix::Minor() is overflowing the actual row count of one of your matrices. I suggest you use your debugger again to try and figure out why this happens; unfortunately my knowledge of matrix arithmetic is not broad enough for me to figure out exactly what is going on.
mehdi_k 28-Oct-12 8:43am
   
Thanks for the try.
I copied your code and duplicated youre problem.
The gdb core dump show the following backtrace infomation:
Core was generated by `./matrix'.
Program terminated with signal 11, Segmentation fault.
[New process 6139]
#0  0x0804880d in CDoubleMatrix::Minor (this=0xbfa04c84, mtx=0x8e60a40, row=0, column=0) at matrix.cpp:132
132                 minorMtx[k][l] = mtx[i][j];
(gdb) bt
#0  0x0804880d in CDoubleMatrix::Minor (this=0xbfa04c84, mtx=0x8e60a40, row=0, column=0) at matrix.cpp:132
#1  0x08048a26 in CDoubleMatrix::Determinant (this=0xbfa04c84, mtx=0x8e60a40) at matrix.cpp:98
#2  0x08048a66 in CDoubleMatrix::Determinant (this=0xbfa04c84, mtx=0x8e603a8) at matrix.cpp:99
#3  0x08048bfd in CDoubleMatrix::Invert (this=0xbfa04c84, mtx=0x8e603a8) at matrix.cpp:54
#4  0x08048e19 in main () at matrix.cpp:181
(gdb) p k
$1 = 8
(gdb) p l
$2 = 0
(gdb) p i
$3 = 9
(gdb)  p j
$4 = 1
(gdb) p minorMtx[8][0]
$5 = 0
(gdb) p mtx[9][1]
Cannot access memory at address 0x59
(gdb) p this->row
$6 = 10
(gdb) p mtx
$7 = (double **) 0x8e60a40


The debug infomation clearly shows the error code. I don't understand your code, but I think there is a clear logic bug in it.
And I guess the following code may be the source of core dump:
C#
double** tempMtx=new double*[row-1];
 for (int i=0;i<row-1;i++)
     tempMtx[i]=new double[col-1];
   

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900