当前位置: 首页 > 知识库问答 >
问题:

分割故障: 11

那弘
2023-03-14

我有一些程序的问题,我已经搜索了关于分割错误,我不太理解他们,我唯一知道的是,大概我试图访问一些我不应该访问的内存。问题是我看到我的代码,不明白我做错了什么。

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

#define   lambda   2.0
#define   g        1.0
#define   Lx       100
#define   F0       1.0
#define   Tf       10
#define   h       0.1
#define   e       0.00001

FILE   *file;

double F[1000][1000000];

void Inicio(double D[1000][1000000]) {
int i;
for (i=399; i<600; i++) {
    D[i][0]=F0;
}
}

void Iteration (double A[1000][1000000]) {
long int i,k;
for (i=1; i<1000000; i++) {
    A[0][i]= A[0][i-1] + e/(h*h*h*h)*g*g*(A[2][i-1] - 4.0*A[1][i-1] + 6.0*A[0][i-1]-4.0*A[998][i-1] + A[997][i-1]) + 2.0*g*e/(h*h)*(A[1][i-1] - 2*A[0][i-1] + A[998][i-1]) + e*A[0][i-1]*(lambda-A[0][i-1]*A[0][i-1]);
    A[1][i]= A[1][i-1] + e/(h*h*h*h)*g*g*(A[3][i-1] - 4.0*A[2][i-1] + 6.0*A[1][i-1]-4.0*A[0][i-1] + A[998][i-1]) + 2.0*g*e/(h*h)*(A[2][i-1] - 2*A[1][i-1] + A[0][i-1]) + e*A[1][i-1]*(lambda-A[1][i-1]*A[1][i-1]);
    for (k=2; k<997; k++) {
        A[k][i]= A[k][i-1] + e/(h*h*h*h)*g*g*(A[k+2][i-1] - 4.0*A[k+1][i-1] + 6.0*A[k][i-1]-4.0*A[k-1][i-1] + A[k-2][i-1]) + 2.0*g*e/(h*h)*(A[k+1][i-1] - 2*A[k][i-1] + A[k-1][i-1]) + e*A[k][i-1]*(lambda-A[k][i-1]*A[k][i-1]);
    }
    A[997][i] = A[997][i-1] + e/(h*h*h*h)*g*g*(A[0][i-1] - 4*A[998][i-1] + 6*A[997][i-1] - 4*A[996][i-1] + A[995][i-1]) + 2.0*g*e/(h*h)*(A[998][i-1] - 2*A[997][i-1] + A[996][i-1]) + e*A[997][i-1]*(lambda-A[997][i-1]*A[997][i-1]);
    A[998][i] = A[998][i-1] + e/(h*h*h*h)*g*g*(A[1][i-1] - 4*A[0][i-1] + 6*A[998][i-1] - 4*A[997][i-1] + A[996][i-1]) + 2.0*g*e/(h*h)*(A[0][i-1] - 2*A[998][i-1] + A[997][i-1]) + e*A[998][i-1]*(lambda-A[998][i-1]*A[998][i-1]);
    A[999][i]=A[0][i];
}
}

main() {
long int i,j;
Inicio(F);
Iteration(F);
file = fopen("P1.txt","wt");
for (i=0; i<1000000; i++) {
    for (j=0; j<1000; j++) {
        fprintf(file,"%lf \t %.4f \t %lf\n", 1.0*j/10.0, 1.0*i, F[j][i]);
    }
}
fclose(file);
}

谢谢你的时间。

共有3个答案

吴康平
2023-03-14

你在运行什么系统?您是否可以访问某种调试器(gdb、VisualStudio的调试器等)?

这将为我们提供有价值的信息,比如程序崩溃的代码行。。。此外,内存量可能会过高。

此外,我是否可以建议您使用命名定义替换数字限制?

像这样的:

#define DIM1_SZ 1000
#define DIM2_SZ 1000000

只要您希望引用数组维度限制,就可以使用这些限制。这将有助于避免键入错误。

卓胜
2023-03-14

您的阵列大约占用8 GB内存(1000 x 1000000 x sizeof(双)字节)。这可能是你问题的一个因素。它是一个全局变量,而不是堆栈变量,所以您可能没问题,但您在这里突破了限制。

将这么多数据写入文件需要一段时间。

您没有检查文件是否已成功打开,这也可能是问题的根源(如果确实失败,很可能是分段错误)。

您确实应该为1000和1000000引入一些命名常量;它们代表什么?

您还应该编写一个函数来进行计算;您可以在C99或更高版本(或C)中使用内联函数。代码中的重复令人痛苦。

您还应该对main()使用C99表示法,并使用显式返回类型(当您不使用argcargv时,最好对参数列表使用val):

int main(void)

出于好奇,我复制了你的代码,将1000次出现的所有情况更改为ROWS,1000000次出现的所有情况更改为COLS,然后创建枚举{ROWS=1000,COLS=10000};(从而将问题大小减少了一个因子100)。我做了一些小的改变,这样它就可以在我首选的编译选项集下干净地编译(不严重:函数前面的静态和主数组;file变成main的本地;错误检查fopen()等)。

然后我创建了第二个副本,并创建了一个内联函数来进行重复计算(第二个用于进行下标计算)。这意味着这个可怕的表达式只写一次——这是非常可取的,因为它确保了一致性。

#include <stdio.h>

#define   lambda   2.0
#define   g        1.0
#define   F0       1.0
#define   h        0.1
#define   e        0.00001

enum { ROWS = 1000, COLS = 10000 };

static double F[ROWS][COLS];

static void Inicio(double D[ROWS][COLS])
{
    for (int i = 399; i < 600; i++) // Magic numbers!!
        D[i][0] = F0;
}

enum { R = ROWS - 1 };

static inline int ko(int k, int n)
{
    int rv = k + n;
    if (rv >= R)
        rv -= R;
    else if (rv < 0)
        rv += R;
    return(rv);
}

static inline void calculate_value(int i, int k, double A[ROWS][COLS])
{
    int ks2 = ko(k, -2);
    int ks1 = ko(k, -1);
    int kp1 = ko(k, +1);
    int kp2 = ko(k, +2);

    A[k][i] = A[k][i-1]
            + e/(h*h*h*h) * g*g * (A[kp2][i-1] - 4.0*A[kp1][i-1] + 6.0*A[k][i-1] - 4.0*A[ks1][i-1] + A[ks2][i-1])
            + 2.0*g*e/(h*h) * (A[kp1][i-1] - 2*A[k][i-1] + A[ks1][i-1])
            + e * A[k][i-1] * (lambda - A[k][i-1] * A[k][i-1]);
}

static void Iteration(double A[ROWS][COLS])
{
    for (int i = 1; i < COLS; i++)
    {
        for (int k = 0; k < R; k++)
            calculate_value(i, k, A);
        A[999][i] = A[0][i];
    }
}

int main(void)
{
    FILE *file = fopen("P2.txt","wt");
    if (file == 0)
        return(1);
    Inicio(F);
    Iteration(F);
    for (int i = 0; i < COLS; i++)
    {
        for (int j = 0; j < ROWS; j++)
        {
            fprintf(file,"%lf \t %.4f \t %lf\n", 1.0*j/10.0, 1.0*i, F[j][i]);
        }
    }
    fclose(file);
    return(0);
}

这个程序写入P2.txt而不是P1.txt。我运行了两个程序并比较了输出文件;输出是相同的。当我在一台大部分闲置的机器(MacBook Pro,2.3 GHz英特尔酷睿i7,16 GiB 1333 MHz RAM,Mac OS X 10.7.5,GCC 4.7.1)上运行程序时,我得到了合理但不完全一致的时间:

Original   Modified
6.334s      6.367s
6.241s      6.231s
6.315s     10.778s
6.378s      6.320s
6.388s      6.293s
6.285s      6.268s
6.387s     10.954s
6.377s      6.227s
8.888s      6.347s
6.304s      6.286s
6.258s     10.302s
6.975s      6.260s
6.663s      6.847s
6.359s      6.313s
6.344s      6.335s
7.762s      6.533s
6.310s      9.418s
8.972s      6.370s
6.383s      6.357s

然而,几乎所有的时间都花在磁盘I/O上。我将磁盘I/O减少到最后一行数据,因此循环的外部I/O变成了:

for (int i = COLS - 1; i < COLS; i++)
Original    Modified
0.168s      0.165s
0.145s      0.165s
0.165s      0.166s
0.164s      0.163s
0.151s      0.151s
0.148s      0.153s
0.152s      0.171s
0.165s      0.165s
0.173s      0.176s
0.171s      0.165s
0.151s      0.169s

在我看来,代码中简化仅写一次可怕的表达式是非常有益的。我当然宁愿维护那个程序,也不愿维护原来的程序。

冀萧迟
2023-03-14

本声明:

double F[1000][1000000];

会占用典型x86系统上的8 * 1000 * 1000000字节。这大约是7.45 GB。在尝试执行代码时,系统可能运行内存溢出,从而导致分段错误。

 类似资料:
  • 以下这段代码在编译期间会产生分段错误: (gdb)运行 启动程序: /home/anna/Desktop/a.out 程序接收信号SIGSEGV,分段故障。 0xb7e97845在strtok()从 /lib/i386-linux-gnu/libc.so.6 更改第5行后,不会引发任何错误。 为什么会发生这种情况?

  • 我有一些必须继续运行的生产关键代码。 将代码视为 我不能相信代码是没有bug的,我需要能够记录问题以便以后调查。 这一次,我知道代码中的某个地方抛出了一个分段错误,我需要至少能够记录该错误,然后重新开始。 阅读这里有几个解决方案,但每一个都是火焰战,声称解决方案实际上弊大于利,没有真正的解释。我也发现了这个我考虑使用的答案,但是我不确定它对我的用例是否有好处。 那么,从C上的分割故障中恢复的最佳方

  • 主要内容:1. 事务失败,2. 系统崩溃,3.磁盘故障要找到问题发生的位置,我们将故障(失败)归纳为以下类别: 事务失败 系统崩溃 磁盘故障 1. 事务失败 当事务无法执行或者它到达无法继续执行的点时发生事务失败。 如果一些事务或进程受到损害,那么这称为事务失败。 事务失败的原因可能是 - 逻辑错误:如果由于某些代码错误或内部错误情况导致事务无法完成,则会发生逻辑错误。 语法错误:它发生在DBMS本身终止活动事务的位置,因为数据库系统无法执行它。 例

  • 问题内容: 我有一个用于捕获任何分段错误或ctrl- c的应用程序。使用下面的代码,我能够捕获分段错误,但是该处理程序一次又一次地被调用。我该如何阻止他们。供您参考,我不想退出我的申请。我只是可以小心释放所有损坏的缓冲区。 可能吗? 处理程序就是这样。 在这里,对于Segmentation故障信号,处理程序被多次调用,并且很明显MyfreeBuffers()给我释放已释放的内存的错误。我只想释放一

  • 我有一个便宜的5美元/月的服务器,1G内存为我的网站处理一些图像。在将GIF图像写入磁盘时,我很少会遇到PHP Imagick的分割错误。 我在console命令上设置了一个内存限制,希望PHP能够首先捕获这个问题,并抛出一个我可以正确处理的异常,但这不起作用。 特别的问题是某些GIF图像会导致它在这行代码中崩溃: 特定的GIF是与成人相关的GIF,因此我不确定是否可以共享它。 以下是我的服务器日

  • 我有一个应用程序,我用它来捕捉任何分割错误或ctrl-c。使用下面的代码,我能够捕获分段错误,但是处理程序被一次又一次地调用。我怎样才能阻止他们。告诉你,我不想退出我的申请。我只是可以小心释放所有损坏的缓冲区。 可能吗? handler是这样的。 这里的分段故障信号,处理程序被多次调用,因为明显的MyFreeBuffers()给我释放已经释放的内存的错误。我只想免费一次,但仍然不想退出应用程序。