0

I'm writing a code which calculates the inverse matrix given a matrix, the thing is, I need that to be included in other code that makes statistical fits, so I need something like a function that receives the size of the matrix (matrix is square matrix) and the matrix itself and returns his inverse, I found something about the syntax and then have this (Gauss-Jordan)

float* inv(int n, float *A)
{
    float* I = 0;//*

    float aux;
    float pivote;

    for(int i = 0; i<n; i++){
        for(int j = 0; j<n; j++){

            if(i == j)
            {
                *(I+i*n+j) = 1.0; //*
            }

            else {
                *(I+i*n+j) = 0.0;
            }
        }
    }

    for(int i = 0; i<n; i++)
    {
        pivote = *(A+i*n+i);

        for(int k = 0; k<n; k++)
        {
            *(A+i*n+k) = *(A+i*n+k)/pivote;//*
            *(I+i*n+k) = *(I+i*n+k)/pivote;//*
        }

        for(int j = 0; j<n; j++)
        {
            if(i!=j)
            {
                aux = *(A+j*n+i);//*

                for(int k = 0; k<n;k++)
                {
                    *(A+j*n+k)=*(A+j*n+k)-aux**(A+i*n+k);//*
                    *(I+j*n+k)=*(I+j*n+k)-aux**(I+i*n+k);//*
                }
            }
        }
    }

    return I;//*
}

There where I put the //* is where I have my doubts, is the syntax correct? the declarations, there in the return should be something else than just I?. When I compile I get a segmentation fault, Following Taekahn recommendations, compiling with sanitizers g++ -fsanitize=address -fsanitize=undefined -fsanitize=leak inverse.cpp I get

inverse.cpp:148:28: runtime error: store to null pointer of type 'float'
AddressSanitizer:DEADLYSIGNAL
=================================================================
==11993==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x00000040338c bp 0x7ffdd6a14510 sp 0x7ffdd6a144b0 T0)
==11993==The signal is caused by a WRITE memory access.
==11993==Hint: address points to the zero page.
    #0 0x40338b in inv(int, float*) (/home/live/med_elect/a.out+0x40338b)
    #1 0x402f30 in main (/home/live/med_elect/a.out+0x402f30)
    #2 0x7f90ffed9e5a in __libc_start_main (/lib64/libc.so.6+0x23e5a)
    #3 0x402289 in _start (/home/live/med_elect/a.out+0x402289)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (/home/live/med_elect/a.out+0x40338b) in inv(int, float*)
==11993==ABORTING

I really appreciate if you can help me, thank you very much in advance and thank you very much for the feedback in the comments, I'm new here with the questions.

UPDATE: Thanks to nasy for the answer, It is important to note that many people mentioned the vector approach, so, to anyone reading this, check the comments and better try the vector approach.

13
  • Have you tried running it under gdb and seeing where the issue is coming from? What about asan and ubsan? Warnings turned on and not ignored? Commented Apr 25, 2022 at 3:35
  • int n = std::atoi(argv[1]); float A[n][n]; is not valid, n is not a constant expression. Commented Apr 25, 2022 at 3:41
  • 2
    Passing 2D arrays as argument to a function and get another 2D array in c++ -- That's the title of this thread, however your post contains 98% of irrelevant code not related to the issue. If the issue is passing and returning a 2D array, then a simple 3 or 4 line main program, showing a declaration, and maybe a 3 or 4 line function that takes the array, changes a value, and returns it back, is all you need to show where you are stuck. That is what is meant by a minimal reproducible example. Inverting matrices, etc. is not relevant to the issue concerning how C++ deals with 2D arrays. Commented Apr 25, 2022 at 3:49
  • Hi @AnoopRana , so you mean setting const int n = std::atoi(argv[1]) instead of int n? Commented Apr 25, 2022 at 3:50
  • 2
    "I need something like a function that receives the size of the matrix (matrix is square matrix)" -- this is more of a C-style approach than an object-oriented C++ approach. In fact, aside from the streaming operations to/from std::cout/std::cin, your code looks more like C than C++. Are you sure C++, not C, is the language you want to use? (Note that the objection someone made to float A[n][n]; disappears if you switch to C, where variable-length arrays are standard.) Commented Apr 25, 2022 at 3:55

2 Answers 2

2

In your second function, you have float *I = 0. Later on, you try to write to this array but you have not allocated it. The way you're indexing your matrices is the flattening approach so you must write float *I = new float[n*n]. There are different approaches, of course, like using dynamic 2D arrays, 2D vectors, etc. as mentioned in the comments.

Sign up to request clarification or add additional context in comments.

2 Comments

Yep it worked, thank you very much. But there is a memory leak, do you know how do I fix that? I changed exactly what you said. I will try the vector approach anyways since it was mentioned multiple times
@CosmeticMichu When you use dynamic arrays, memory is allocated on the heap for your program and will not be freed until the program ends or you delete it yourself during the program. You should deallocate it using delete[] arrName (since you used new[]) after you are done with the array, for example after printing out the result.
0

The problem is that the pointer I doesn't point to any object and you've the following statement:

*(I+i*n+j) = 1.0; //undefined behavior

The above statement leads to undefined behavior. Imagine what happens when i and j are both 0 in the first iteration. Then you're dereferencing I which doesn't point to any float object and thus this is undefined behavior.

Undefined behavior means anything1 can happen including but not limited to the program giving your expected output. But never rely(or make conclusions based) on the output of a program that has undefined behavior. The program may just crash.

So the output that you're seeing(maybe seeing) is a result of undefined behavior. And as i said don't rely on the output of a program that has UB. The program may just crash which happens in your case.

So the first step to make the program correct would be to remove UB. Then and only then you can start reasoning about the output of the program.

Also, it would be better to use std::vector than doing manual memory management using new and delete.


1For a more technically accurate definition of undefined behavior see this where it is mentioned that: there are no restrictions on the behavior of the program.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.