首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >分段故障: 11

分段故障: 11
EN

Stack Overflow用户
提问于 2012-10-07 03:09:17
回答 4查看 396.9K关注 0票数 63

我遇到了一些程序的问题,我搜索了分段错误,我不是很好地理解它们,我唯一知道的是我可能正在尝试访问一些不应该访问的内存,问题是我看到了我的代码,但不知道我做错了什么。

代码语言:javascript
运行
复制
#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);
}

耽误您时间,实在对不起。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-10-07 03:14:41

此声明:

代码语言:javascript
运行
复制
double F[1000][1000000];

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

票数 131
EN

Stack Overflow用户

发布于 2012-10-07 03:18:35

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

将如此多的数据写入文件将需要一段时间。

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

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

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

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

代码语言:javascript
运行
复制
int main(void)

出于好奇,我复制了您的代码,将所有出现的1000改为ROWS,将所有出现的1000000改为COLS,然后创建了enum { ROWS = 1000, COLS = 10000 }; (从而将问题大小减少了100倍)。我做了一些小改动,以便它可以在我首选的一组编译选项下干净地编译(没什么大不了的:函数前面的static和主数组;file变成main的本地变量;错误检查fopen(),等等)。

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

代码语言:javascript
运行
复制
#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。我运行了这两个程序,并比较了输出文件;输出是相同的。当我在一台大部分空闲的机器上运行这些程序时( Mac,2.3 GHz英特尔酷睿i7,16 GiB 1333 MHz内存,Mac 10.7.5,GCC 4.7.1),我得到了合理但不完全一致的时间:

代码语言:javascript
运行
复制
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循环变成:

代码语言:javascript
运行
复制
for (int i = COLS - 1; i < COLS; i++)

大大减少了计时,并且更加一致:

代码语言:javascript
运行
复制
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

在我看来,代码中只写出一次可怕的表达式的简化是非常有益的。我当然更愿意维护这个程序,而不是原来的程序。

票数 41
EN

Stack Overflow用户

发布于 2012-10-07 03:12:27

你在什么系统上运行?您是否有权访问某种调试器(gdb、visual studio的调试器等)?

这将为我们提供有价值的信息,比如程序崩溃的代码行。此外,内存的大小可能会令人望而却步。

另外,我可以建议您用命名定义替换数字限制吗?

因此:

代码语言:javascript
运行
复制
#define DIM1_SZ 1000
#define DIM2_SZ 1000000

只要您想引用数组的维数限制,就可以使用它们。这将有助于避免输入错误。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12762944

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档