gcc 仅在Windows计算机上遇到C代码中的分段故障问题

tvmytwxo  于 12个月前  发布在  Windows
关注(0)|答案(2)|浏览(131)

我试图将一个函数slice的输出切片传递给另一个函数,但是我在append_2d_slice切片函数的第93行收到Segmentation fault error。我注解了导致问题的行。我怀疑我以错误的方式将slice变量传递给函数,但我不确定。
代码如下:

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

字符串
以下是脚本中使用的txt文件的链接:https://drive.google.com/drive/folders/1pmSkKrxS7IWDGyPiyl0SuNEh3gidmyFS?usp=drive_link
编辑_0:
上面未注解的代码行append_2d_slice(mmm, UUo, nz, nx, nt - 1 - it);可以在Colab和wsl(Linux的Windows子系统)上工作,但是它不能在Windows上工作。问题是为什么?它可能是gcc的版本吗?
gcc版本Windows:gcc.exe(MinGW.org GCC-6.3.0-1)6.3.0 gcc版本Linux:gcc(Ubuntu 9.4.0- 1ubuntu 1 ~20.04.2)9.4.0
编辑_1:好吧,我配置了runner,这样代码就可以在WSL终端上运行,它解决了这个问题,但我仍然不确定为什么它不能在Windows上工作,我怀疑是gcc版本。

vx6bjr1n

vx6bjr1n1#

“* 怀疑变量错误地传递到函数... *”在这堆代码中很难分辨。虽然复制/粘贴是一种权宜之计,但当你冲向终点线时,就像“兔子和兔子”的寓言一样,权宜之计又回来了。
下面是新生成的处理核心的第二个版本的简化(未经测试)。虽然应该避免过早的优化是正确的,但是当一个人走向绝望的深渊时,必须意识到这个经验法则是重复的功能。

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

字符串
虽然这可能会也可能不会回答OP的问题,但这种简化至少为更简单地跟踪问题打开了一扇Windows。(在第二个版本中,单个元素的设置确实看起来很奇怪。是否有一个丢失的循环?)

tcomlyy6

tcomlyy62#

如果其他人也有类似的问题,C代码在Linux,WSL,Colab上运行没有问题,但在Windows机器上没有。配置你的code_runner,使其在WSL终端上运行。在我的情况下,我使用Visual Studio Code。我在这里包含了显示如何在Visual Studio Code上配置的链接。

相关问题