For my linear algebra code I need to allocate memory for a lower triangular matrix,
represented by a one dimensional array. I was experimenting with how many elements I can allocate and
stumbled upon a weird behaviour. If I set double bottom_row_final
to be anything above 240.0
, malloc
fails and my machine cannot allocate enough memory, but setting it to 410.0
, malloc
does not fail, and
my code crashes later in the for
loop when initialising the array after 30
or so iterations (out of
bounds indexing excluded as possible error source). Does someone know what is happening here?
//array.c
#include <stdio.h>
#include <stdlib.h>
void vector_alloc(int N, double **pM) {
if ((*pM = (double *)malloc(N * sizeof(double))) == NULL) {
printf("Error: malloc failed!\n");
exit(0);
}
}
void vector_free(double **pM) {
free(*pM);
*pM = NULL;
}
int main(void) {
//-----------------------------------------------------------------------------------------------------------------------
double grid_step = 0.0125;
double bottom_row_final = 410.0; // 230 works, 240 and above does not allocate anymore, but 410 does
int bottom_row_elements = (int)(bottom_row_final / grid_step) 1;
int lower_triangular_matrix_elements = bottom_row_elements * (bottom_row_elements 1) / 2;
double *matrix;
vector_alloc(lower_triangular_matrix_elements, &matrix);
int index_jumper = 0;
//-----------------------------------------------------------------------------------------------------------------------
for (int i = 0; i <= bottom_row_elements; i ) {
if (i < bottom_row_elements) {
printf("\n%d\t%d", index_jumper, lower_triangular_matrix_elements - 1);
matrix[index_jumper] = 1.0;
printf("\tInitialized with value");
index_jumper = (bottom_row_elements - i);
}
}
//-----------------------------------------------------------------------------------------------------------------------
vector_free(&matrix);
}
I tried debugging the code and I got segmentation errors (obviously) but malloc
should not
even be able to allocate the memory for double bottom_row_final
above 240.0
.
CodePudding user response:
The problem is here:
int lower_triangular_matrix_elements = bottom_row_elements * (bottom_row_elements 1) / 2;
When bottom_row_elements
is larger than 46340
, the multiplication causes a signed arithmetic overflow, which has undefined behavior. Depending on the actual value, the result may be negative or positive, causing malloc()
to either fail because the request is far too large, or to succeed but with an amount of memory that is lower than needed, causing further undefined behavior when accessing beyond the end of the allocated size.
You should use size_t
for the computations instead of int
.
//array.c
#include <stdio.h>
#include <stdlib.h>
void vector_alloc(size_t N, double **pM) {
// Allocate the array, initialized to 0.0, assuming IEEE 754 doubles
if ((*pM = (double *)calloc(N, sizeof(double))) == NULL) {
printf("Fehler: malloc fehlgeschlagen!\n");
exit(0);
}
}
void vector_free(double **pM) {
free(*pM);
*pM = NULL;
}
int main(void) {
//-----------------------------------------------------------------------------------------------------------------------
double grid_step = 0.0125;
double bottom_row_final = 410.0;
size_t bottom_row_elements = (size_t)(bottom_row_final / grid_step) 1;
size_t lower_triangular_matrix_elements = bottom_row_elements * (bottom_row_elements 1) / 2;
double *matrix = NULL;
vector_alloc(lower_triangular_matrix_elements, &matrix);
size_t index_jumper = 0;
//-----------------------------------------------------------------------------------------------------------------------
for (size_t i = 0; i < bottom_row_elements; i ) {
printf("\n%zu\t%zu",
index_jumper, lower_triangular_matrix_elements - 1);
matrix[index_jumper] = 1.0;
printf("\tInitialized with value");
index_jumper = bottom_row_elements - i;
}
//-----------------------------------------------------------------------------------------------------------------------
vector_free(&matrix);
}
CodePudding user response:
I tried replicating your problem, but I could not. Are you sure that malloc() really worked? Do you get an error message, running it without debug?