cmemory-managementmemory-leaks

# Experiencing periodic issues in a C code , suspecting a memory allocation problem

The provided c code runs periodically , I checked the debugger it indicates that the problem is in the line : `UUo[irx][i] += dt * dt * slice[i][it];` which is located in the first loop of `awe_2d_heterogeneous_8th_order_data_time_reverse` function.

Here is the code :

``````#include <stdio.h>
#include <stdlib.h>
#include <math.h>

void awe_2d_heterogeneous_8th_order_data_time_reverse(
double** UUo, double** UUm, int nx, int ny, double dx, double dy,
double dt, double** v, double** slice, int it, double rx
) {
// Get dimensions of the wavefield
int irx = (int)(rx / dx); // Force to be integer

// Inject wavelet
for (int i = 0; i < nx; i++) {
//   printf("i: %d\n", i);
UUo[irx][i] += dt * dt * slice[i][it]; //Debugger points to this line

}

// Define Courant numbers (squared)
double dtdx2 = (dt / dx) * (dt / dx);
double dtdy2 = (dt / dy) * (dt / dy);

// Update solution
for (int i = 4; i < nx - 4; i++) {
for (int j = 4; j < ny - 4; j++) {
UUm[i][j] = 2 * UUo[i][j] - UUm[i][j] + dtdx2 * v[i][j] * v[i][j] * (
-1.0/560 * UUo[i - 4][j]
+ 8.0/315 * UUo[i - 3][j]
- 1.0/5 * UUo[i - 2][j]
+ 8.0/5 * UUo[i - 1][j]
- 205.0/72 * UUo[i][j]
+ 8.0/5 * UUo[i + 1][j]
- 1.0/5 * UUo[i + 2][j]
+ 8.0/315 * UUo[i + 3][j]
- 1.0/560 * UUo[i + 4][j]) + dtdy2 * v[i][j] * v[i][j] * (
-1.0/560 * UUo[i][j - 4]
+ 8.0/315 * UUo[i][j - 3]
- 1.0/5 * UUo[i][j - 2]
+ 8.0/5 * UUo[i][j - 1]
- 205.0/72 * UUo[i][j]
+ 8.0/5 * UUo[i][j + 1]
- 1.0/5 * UUo[i][j + 2]
+ 8.0/315 * UUo[i][j + 3]
- 1.0/560 * UUo[i][j + 4]);
}
}
}

void append_2d_slice(double*** dest, double** src, int nx, int ny, int nt) {
for (int i = 0; i < nx; i++) {
for (int j = 0; j < ny; j++) {
dest[i][j][nt] = src[i][j];
}
}
}

void write_text_file_slice(double** slice, int nx, int ny, const char* filename) {
FILE *file = fopen(filename, "w");
if (file == NULL) {
fprintf(stderr, "Error opening file for writing.\n");
exit(1);
}

// Write slice data to the text file
for (int i = 0; i < nx; i++) {
for (int j = 0; j < ny; j++) {
fprintf(file, "%.50lf ", slice[i][j]);
}
fprintf(file, "\n");
}

fclose(file);
}

int main() {
// Define constants and arrays
int nz = 300;
int nx = 298;
double dz = 5.0;
double dx = 5.0;
double t0 = 0.05;
double CC = 0.5;
int nt = 2000;
double sx = 25;
double sy = 800;

// Initialize UUo and UUm with zeros
double** UUo = (double**)malloc(nz * sizeof(double*));
double** UUm = (double**)malloc(nz * sizeof(double*));
double** v = (double**)malloc(nz * sizeof(double*));
double** slice = (double**)malloc(nx * sizeof(double*));

for (int i = 0; i < nz; i++) {
UUo[i] = (double*)malloc(nx * sizeof(double));
UUm[i] = (double*)malloc(nx * sizeof(double));
v[i] = (double*)malloc(nx * sizeof(double));
}

for (int i = 0; i < nx; i++) {
slice[i] = (double*)malloc(nt * sizeof(double));
}

// Initialize mmm with zeros
double*** mmm = (double***)malloc(nz * sizeof(double**));
for (int i = 0; i < nz; i++) {
mmm[i] = (double**)malloc(nx * sizeof(double*));
for (int j = 0; j < nx; j++) {
mmm[i][j] = (double*)malloc(nt * sizeof(double));
}
}

// Time stepping parameters
double dt = CC * dz / 5560.328125; // Assuming 'v' is the maximum value
double t[nt];
for (int i = 0; i < nt; i++) {
t[i] = i * dt;
}

FILE *fileS = fopen("slice.txt", "r");
if (fileS == NULL) {
fprintf(stderr, "Error opening file.\n");
perror("fopen");
return 1; // Exit with an error code
}

for (int i = 0; i < nx; i++) {
for (int j = 0; j < nt; j++) {
if (fscanf(fileS, "%lf", &slice[i][j]) != 1) {
fclose(fileS);
return 1; // Exit with an error code
}
}
}
fclose(fileS);

// Read 'v' from the file
FILE *file = fopen("marmousi.txt", "r");
if (file == NULL) {
fprintf(stderr, "Error opening file.\n");
perror("fopen");
return 1; // Exit with an error code
}

for (int i = 0; i < nz; i++) {
for (int j = 0; j < nx; j++) {
if (fscanf(file, "%lf", &v[i][j]) != 1) {
fclose(file);
return 1; // Exit with an error code
}
}
}

fclose(file);

double rx = 25;

for (int it = nt - 1; it > 1900; it--) {
//printf("%d\n",it);
awe_2d_heterogeneous_8th_order_data_time_reverse(UUo, UUm, nz, nx, dz, dx, dt, v, slice, it, rx);
double** tmp = UUo;
UUo = UUm;
UUm = tmp;
append_2d_slice(mmm, UUo, nz, nx, nt - 1 - it);
}

double** slicep = mmm[5];

write_text_file_slice(slicep, nx, nt, "slicep.txt");

// Free allocated memory
for (int i = 0; i < nz; i++) {
free(UUo[i]);
free(UUm[i]);
free(v[i]);
}
free(UUo);
free(UUm);
free(v);

for (int i = 0; i < nx; i++) {
free(slice[i]);
}
free(slice);

for (int i = 0; i < nz; i++) {
for (int j = 0; j < nx; j++) {
free(mmm[i][j]);
}
free(mmm[i]);
}
free(mmm);

return 0;
}
``````

I don't think the problem is in the indexes since the program works occasionally. I may miss something related with memory allocation.

Solution

1. Your code segfaults for me 100% of the time. In `main()` you call:

``````    awe_2d_heterogeneous_8th_order_data_time_reverse(UUo, UUm, nz, nx, dz, dx, dt, v, slice, it, rx);
``````

but confusingly change `main()`:`nx` to `awe_...()`:`ny`:

``````void awe_2d_heterogeneous_8th_order_data_time_reverse(
double** UUo, double** UUm, int nx, int ny, double dx, double dy,
double dt, double** v, double** slice, int it, double rx
) {
``````

so offending loop now result in out of bound access to both `UUo` and `slice`:

`````` for (int i = 0; i < nx; i++) {
//   printf("i: %d\n", i);
UUo[irx][i] += dt * dt * slice[i][it]; //Debugger points to this line

}
``````

Using `ny` as the upper bound of the loop is probably the smallest change that resolves the segfault:

`````` for (int i = 0; i < ny; i++)
UUo[irx][i] += dt * dt * slice[i][it];
``````
2. This leaves us with valgrind "More than 10000000 total errors detected" and it seems a lot of them are "Conditional jump or move depends on uninitialised value(s)" which is to @Fe2OS3 point of using `calloc()` instead of `malloc()` for zero initialized memory:

`````` double **UUo = malloc(nz * sizeof *UUo);
double **UUm = malloc(nz * sizeof *UUm);
double **v = malloc(nz * sizeof *v);
double **slice = malloc(nx * sizeof *slice);
for (int i = 0; i < nz; i++) {
UUo[i] = calloc(nx, sizeof *UUo[i]);
UUm[i] = calloc(nx, sizeof *UUm[i]);
v[i] = calloc(nx, sizeof *v[i]);
}
for (int i = 0; i < nx; i++)
slice[i] = calloc(nt, sizeof *slice[i]);

// Initialize mmm with zeros
double ***mmm = malloc(nz * sizeof *mmm);
for (int i = 0; i < nz; i++) {
mmm[i] = calloc(nx, sizeof *mmm[i]);
for (int j = 0; j < nx; j++) {
mmm[i][j] = calloc(nt, sizeof *mmm[i][j]);
}
}
``````