【问题标题】:Weird error/result when running code... C fdtd method运行代码时出现奇怪的错误/结果... C fdtd 方法
【发布时间】:2017-09-15 15:54:35
【问题描述】:

每当我启动一个 for 循环为数组赋值时,它会在另一个循环中修改结果,尽管在该循环中没有被调用...问题来自 epsR... 以某种方式评论/取消注释它会更改结果时间步进循环(计算 elec/mag 场)。为什么?当带有 espR 的 for 循环和 if 语句被注释掉时,结果很好。如果没有注释掉,我会得到无意义的结果!

会不会是内存损坏?我看不出是什么导致了这个问题。

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

#define SIZE 200

int main()
{
    double ez[SIZE]={0.}, hy[SIZE]={0.}, imp0=377.0;
    double epsR[SIZE];
    int qTime, maxTime=650, mm;
    char basename[80]="sim", filename[100];
    int frame=0;
    FILE *snapshot;
    /* Init */
    for (mm=0;mm<SIZE;mm++){
        ez[mm]=0.0;
    }
    for (mm=0;mm<SIZE-1;mm++){
        hy[mm]=0.0;
    }
    /* Leaving this loop uncommented modifies the results
     of the loop time stepping*/
    for (mm=0;mm<SIZE;mm++){
        if (mm<100){
            epsR[mm]=1.0;
        }
        else {
            epsR[mm]=9.0;
        }
    }

    /* time stepping*/
    for (qTime=0; qTime<maxTime;qTime++){

        /*Mag field*/
        hy[SIZE-1]=hy[SIZE-2];

        for (mm=0;mm<SIZE-1;mm++){
            hy[mm]=hy[mm]+(ez[mm+1]-ez[mm])/imp0;
        }
        hy[49]-=exp(-(qTime-30.)*(qTime-30.)/100.)/imp0;
        /*Elec field*/
        ez[0]=ez[1];
        ez[SIZE-1]=ez[SIZE-2];

        for (mm=0;mm<SIZE;mm++){
            ez[mm]=ez[mm]+(hy[mm]-hy[mm-1])*imp0/9.0;
        }
        ez[50]+=exp(-(qTime+0.5-(-0.5)-30.)*(qTime+0.5-(-0.5)-30.0)/100.);

        /*Write*/
        if (qTime % 10==0){
            sprintf(filename,"%s.%d", basename, frame++);
            snapshot=fopen(filename,"w");
            for (mm=0;mm<SIZE;mm++){
                fprintf(snapshot,"%g\n",ez[mm]);
            }
        fclose(snapshot);
        }
    }
    return 0;
}

【问题讨论】:

  • 如果你使用调试器,你可以很快找到。
  • for (mm=0;mm&lt;SIZE;mm++){ ez[mm]=ez[mm]+(hy[mm]-hy[mm-1])*imp0/9.0; } 越界访问,未定义行为。
  • 在 ex 和 hy 之后初始化 epsR 以某种方式解决了问题(在 ex/hy 的两个 for 循环之后)...
  • @mooder 因此,您找到了一种通过随机代码更改来掩盖未定义行为的方法。恭喜。
  • @EOF,我对编码很陌生。我一直在关注一本关于 FDTD 方法的书,但代码似乎有问题。我尝试使用代码块进行调试,但我不知道它有什么帮助?当 epsR 在 char basename[80]="sim", filename[100]; 行之前初始化时会出现问题

标签: c simulation


【解决方案1】:

在这个循环中:

for (mm=0;mm<SIZE;mm++){
    ez[mm]=ez[mm]+(hy[mm]-hy[mm-1])*imp0/9.0;
}

在第一次迭代中,mm == 0

所以hy[mm-1]hy[-1],这是越界的未定义行为。这意味着任何事情都可能发生,因为它正在访问随机数据。

如果您希望它访问最后一个元素,请像这样检查:

for (mm=0;mm<SIZE;mm++){
    if(mm==0) {
        ez[0]=ez[0]+(hy[0]-hy[SIZE - 1])*imp0/9.0;
    } else {    
        ez[mm]=ez[mm]+(hy[mm]-hy[mm-1])*imp0/9.0;
    }
}

【讨论】:

  • “这意味着任何事情都可能发生,因为它正在访问随机数据。”去掉逗号后面的部分,答案基本正确。
  • hy[-1] 将访问 hy[18446744073709551615] (或 hy[4294967295] 如果它是 32 位)对吗?
  • 谢谢 我觉得自己很笨。
  • 没有。根据 C 的规则,越界访问数组不会访问另一个对象。它是未定义的。句号。 C 语言不做任何保证。当遇到未定义的行为时,编译器不需要生成行为一致的代码。典型的说法是,当未定义的行为被触发时,程序可以让你的鼻子喷出恶魔。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-07
  • 2021-11-05
  • 2022-01-10
  • 1970-01-01
  • 1970-01-01
  • 2014-12-20
相关资源
最近更新 更多