Home > Software engineering >  What's causing SIGSEV when my matrix is a certain size?
What's causing SIGSEV when my matrix is a certain size?

Time:10-15

Just having an issue here with SIGSEV.

The role of this program is to build a matrix of n * n, which is the first command line argument, and then furthermore fills out the matrix from integers sourced from command line arguments.

The output then consists of the main diagonal of this matrix summed together

Example:
1 2 3
4 5 6
7 8 9

1 5 9 = 15

Sample input:
./file-name 3 1 2 3 4 5 6 7 8 9
Sample output:
15

However I'm very confused, as it works with all matrices under size 5, but once I go over, I get this address boundary error. Anyone know why?

Error:

fish: Job 1, './file-name 5...' terminated by signal SIGSEV (Address boundary error)

Code:

/* Description: Takes integer arguments from command line
 *      First argument signafies matrix's size, (n * n)
 *      Remaining arguments fill matrix.
 *      Then the main diagonal of the matrix is summed
 *      and outputted
 * Input: Multiple integers as cmd line arguments, first signifies 
 *    matrix size (n * n)
 * Output: A single integer, the sum of the diagonals
 *
 */

// Includes
#include <stdio.h>
#include <stdlib.h>

// Function Prototypes
void fill_matrix(int **matrix, int n, char **argv);
int sum_diag_matrix(int **matrix, int n);

// Main Function
int main(int argc, char **argv) {
    // Take cmd line args
    int n = atoi(argv[1]);
    // Assign and allocate double pointer enough memory for matrix of size n
    int **matrix = (int **) malloc(n * sizeof(int));
    // Assign pointers inside double pointer of matrix enough memory for vector of size n
    for ( int i = 0; i < n;   i ) {
        *(matrix   i) = (int *) malloc(n * sizeof(int));
    }
    // Call fill_matrix function to fill our matrix from cmd line args
    fill_matrix(matrix, n, argv);

    // Assign total to the return of our sum_diag_matrix function
    int total = sum_diag_matrix(matrix, n);
    // Output our total
    printf("%i\n", total);
    // Return 0 to signal script running correctly
    return 0;
}

// Fill matrix function fills the matrix of passed size n from passed array
void fill_matrix(int **matrix, int n, char **arr) {
    // Initialize element integer to keep track of what element we're on
    int element = 0;
    // Nested loop iterates over matrix, filling out the values from the given array
    for ( int i = 0; i < n;   i) {
        for ( int j = 0; j < n;   j) {
            *(*(matrix   i)   j) = atoi(arr[element   2]);
            printf("%i\n", *(*(matrix   i)   j));
            element  ;
        }
    }
    
    // Return nothing for void
    return;
}

// Sum diag matrix function sums the main diagonal of the matrix passed of passed size n
int sum_diag_matrix(int **matrix, int n) {
    // Initialize total to keep track of sum
    int total = 0;
    // Iterate over diagonal elements of matrix
    for ( int i = 0; i < n;   i) {
        total  = *(*(matrix   i)   i);
    }
    
    // Return total sum
    return total;
}

I'm new to pointers and such, so I'm trying to apply them everywhere, so potentially it could be that? Regardless I'm not too sure and I'm slightly stumped.

Any help would be appreciated!

CodePudding user response:

-fsanitize=address is usually a great tool in debugging these kinds of problems. Even with the input you claim works, it spots the problem:

==1==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000018 at pc 0x000000401284 bp 0x7fff8ff3b540 sp 0x7fff8ff3b538
WRITE of size 8 at 0x602000000018 thread T0
    #0 0x401283 in main /app/example.c:28
    #1 0x7fd9788e9082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6 0x24082)
    #2 0x40111d in _start (/app/output.s 0x40111d)

0x60200000001c is located 0 bytes to the right of 12-byte region [0x602000000010,0x60200000001c)
allocated by thread T0 here:
    #0 0x7fd978b72bbf in malloc (/opt/compiler-explorer/gcc-12.2.0/lib64/libasan.so.8 0xbbbbf)
    #1 0x40122c in main /app/example.c:25
    #2 0x7fd9788e9082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6 0x24082)

SUMMARY: AddressSanitizer: heap-buffer-overflow /app/example.c:28 in main
Shadow bytes around the buggy address:

It says that at line 28, we're exceeding the memory allocated at line 25.

int **matrix = (int **) malloc(n * sizeof(int));          // Line 25
// Assign pointers inside double pointer of matrix enough memory for vector of size n
for ( int i = 0; i < n;   i ) {
    *(matrix   i) = (int *) malloc(n * sizeof(int));      // Line 28
}

Immediately, we see you use sizeof(int) and assign to int **, which is wrong. Fixed:

int **matrix = (int **) malloc(n * sizeof(int *));

(Also, you leak the memory on exit, which isn't a problem in systems with virtual memory like your desktop PC.)


Using the following macro would would also have caught the problem.

#define MALLOC(t, n) ( (t*)malloc(sizeof(t) * n) )
#define REALLOC(p, t, n) ( (t*)realloc(p, sizeof(t) * n) )
int **matrix = MALLOC(int*, n);   // Warns if `int` is used instead of `int*`.
for ( int i = 0; i < n;   i ) {
    matrix[i] = MALLOC(int, n);
}
  • Related