Experiencing Segmentation Fault issue in C code on Windows machine only

I’m trying to pass the slice of the output of one function slice to another function, however I receive Segmentation fault error at line 93 in append_2d_slice slice function. I commented line which causes the problem. I suspect I’m passing slice variable to the function in a wrong way, but I’m not sure.

Here is the code:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
//Works on Collab
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 < ny; i++) {
     //   printf("i: %d\n", i);
        UUo[irx][i] += dt * dt * slice[i][it];

    }

    // 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 awe_2d_explicit_solver_heterogeneous_8th_order(
    double** UUo, double** UUm, int nx, int ny, double dx, double dy,
    double dt, double** v, double* F, int it, double sx, double sy
) {
    // Define Courant numbers (squared)
    double dtdx2 = (dt / dx) * (dt / dx);
    double dtdy2 = (dt / dy) * (dt / dy);

    // Source location
    int isx = (int)(sx / dx);
    int isy = (int)(sy / dy);

    // Inject wavelet
    UUo[isx][isy] += dt * dt * F[it];

    // Update solution without using slicing
    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]; // Debugger Points here Segmenation fault
        }
    }
}

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 F[nt];
    double sx = 25;
    double sy = 800;

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

    for (int i = 0; i < nz; i++) {
        UUo[i] = calloc(nx, sizeof *UUo[i]);
        UUm[i] = calloc(nx, sizeof *UUm[i]);
        UUo1[i] = calloc(nx, sizeof *UUo1[i]);//addition
        UUm1[i] = calloc(nx, sizeof *UUm1[i]);//addition
        v[i] = calloc(nx, sizeof *v[i]);
    }

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

    // 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]);
        }
    }

    // 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;
    }

    // Define forcing function
    double ss = 0.01;
    for (int i = 0; i < nt; i++) {
        F[i] = (1.0 - ((t[i] - t0) / ss) * ((t[i] - t0) / ss)) * exp(-((t[i] - t0) * (t[i] - t0)) / (2 * ss * ss));
    }

    // 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) {
                fprintf(stderr, "Error reading from file.\n");
                fclose(file);
                return 1; // Exit with an error code
            }
        }
    }
    fclose(file);
        
    printf("Forward Propagation...\n");

    for (int it = 0; it < nt; it++) {
        awe_2d_explicit_solver_heterogeneous_8th_order(UUo1, UUm1, nz, nx, dz, dx, dt, v, F, it, sx, sy);
        // Swap UUo and UUm
        double** tmp = UUo1;
        UUo1 = UUm1;
        UUm1 = tmp;
        append_2d_slice(fff, UUo1, nz, nx, it);
    }
    printf("Forward Propagation Done !\n");
    double** slice = fff[5];

    write_text_file_slice(slice, nx, nt, "slice.txt");
    
    printf("Backward Propagation...\n");
    for (int it = nt - 1; it > 0; it--) {
        //printf("%d\n",it);
        awe_2d_heterogeneous_8th_order_data_time_reverse(UUo, UUm, nz, nx, dz, dx, dt, v, slice, it, sx);
        double** tmp = UUo;
        UUo = UUm;
        UUm = tmp;
        append_2d_slice(mmm, UUo, nz, nx, nt - 1 - it);// When I uncomment this part the code stops working and  Debugger Points at line 93 on Windows Machine
    }
    printf("Backward Propagation Done !\n");
    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(UUo1[i]);
        free(UUm1[i]);
        free(v[i]);
    }
    free(UUo);
    free(UUm);
    free(UUo1);
    free(UUm1);
    free(v);

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

    return 0;
}

Here is the link to txt file used in script : https://drive.google.com/drive/folders/1pmSkKrxS7IWDGyPiyl0SuNEh3gidmyFS?usp=drive_link

Edit_0:

The code above with uncommented line append_2d_slice(mmm, UUo, nz, nx, nt - 1 - it); works on Colab and wsl (Windows Subsystem for Linux) , however it does not work on Windows . The question is Why ? Could it be version of gcc ?

gcc version on Windows : gcc.exe (MinGW.org GCC-6.3.0-1) 6.3.0
gcc version on Linux: gcc (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0

Edit_1:
Okay, I configured runner so that code runs on WSL Terminal and it solves the issue, but I’m still not sure why it doesn’t work on Windows I suspect version of gcc.

  • 1

    double ***mmm pointer to pointer to pointer, holy moley. Your variable naming is pretty bad which makes this super hard to even attempt at debugging by an outsider. Why not give the variables a more meaningful name. The code gets compiled to machine code so there is no overhead.

    – 

  • What do you mean by ‘pointer to pointer to pointer’ ? It is done to allocate space for 3D variable. Since I’m trying to append 2d slices UUo to it. The similar operation done to append UUo1 slices to 3d fff variable.

    – 




  • 2

    Three Star Programmer: it’s not a compliment.

    – 

  • 1

    @AllanWind Done.

    – 

  • 1

    If your question now is why your code behaves differently then you revise the question and tag the question with windows and probably tell what compiler you use. I don’t use windows so I can’t help you. I am not arguing with you just trying help revise the question so someone might be able to.

    – 




suspecting wrong passage of variable to function…” Hard to tell in this morass of code. While copy/paste is an expedient solution when racing toward a finish line, like the “Tortoise and Hare” fable, expediency comes back to bite at its own discretion.

Below is a simplification (untested) of the newly spawned 2nd version of the heart of the processing. While it’s true that pre-mature optimisation should be avoided, this rule-of-thumb must be tempered by realising when one is headed toward the pit of despair that is replicated functionality.

void run(
    double** UUo, double** UUm, double** v,
    int nx, int ny,
    double dx, double dy, double dt
) {
    // coefficients as array of constants.
    const double arr[] = { 205.0/72.0, 8.0/5.0, 1.0/5.0, 8.0/315.0, 1.0/560.0 };
    // Courant numbers (squared)
    const double dtdx2 = (dt / dx) * (dt / dx);
    const double dtdy2 = (dt / dy) * (dt / dy);

    for (int i = 4; i < nx - 4; i++)
        for (int j = 4; j < ny - 4; j++) {
            double someSqr = v[i][j] * v[i][j];
            UUm[i][j]
                = 2 * UUo[i][j] - UUm[i][j]
                + dtdx2 * someSqr * (
                    - arr[4] * UUo[i - 4][j]
                    + arr[3] * UUo[i - 3][j]
                    - arr[2] * UUo[i - 2][j]
                    + arr[1] * UUo[i - 1][j]
                    - arr[0] * UUo[i + 0][j]
                    + arr[1] * UUo[i + 1][j]
                    - arr[2] * UUo[i + 2][j]
                    + arr[3] * UUo[i + 3][j]
                    - arr[4] * UUo[i + 4][j] )
                + dtdy2 * someSqr * (
                    - arr[4] * UUo[i][j - 4]
                    + arr[3] * UUo[i][j - 3]
                    - arr[2] * UUo[i][j - 2]
                    + arr[1] * UUo[i][j - 1]
                    - arr[0] * UUo[i][j + 0]
                    + arr[1] * UUo[i][j + 1]
                    - arr[2] * UUo[i][j + 2]
                    + arr[3] * UUo[i][j + 3]
                    - arr[4] * UUo[i][j + 4] )
            ;
        }
}

// Preliminary processing for this version...
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 < ny; i++)
        UUo[irx][i] += dt * dt * slice[i][it];

    // Update solution
    run( UU0, UUm, v, nx, ny, dx, dy, dt );
}

// ... and preliminary processing for this version.
void awe_2d_explicit_solver_heterogeneous_8th_order(
    double** UUo, double** UUm, int nx, int ny, double dx, double dy,
    double dt, double** v, double* F, int it, double sx, double sy
) {
    // Source location
    int isx = (int)(sx / dx);
    int isy = (int)(sy / dy);

    // Inject wavelet
    UUo[isx][isy] += dt * dt * F[it];

    // Update solution without using slicing
    run( UU0, UUm, v, nx, ny, dx, dy, dt );
}

While this may or may not answer the OP’s problem, this simplification at least opens the window to tracking down the problem much more simply. (The setting of a single element in the 2nd version does seem odd. Is there a missing loop?)

If someone else has similar issue, C code running without issues on Linux, WSL, Colab but not on Windows machine.Configure your code_runner so that it runs on WSL Terminal. In my case I’m using Visual Studio Code. I include here the link which shows how to configure that on Visual Studio Code.

Leave a Comment