我遇到了一些程序的问题,我搜索了分段错误,我不是很好地理解它们,我唯一知道的是我可能正在尝试访问一些不应该访问的内存,问题是我看到了我的代码,但不知道我做错了什么。
#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);
}耽误您时间,实在对不起。
发布于 2012-10-07 03:14:41
此声明:
double F[1000][1000000];在典型的x86系统上将占用8* 1000 * 1000000字节。这大约是7.45 GB。在尝试执行代码时,您的系统可能会耗尽内存,这会导致分段错误。
发布于 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表示法,并使用显式返回类型(当您不使用argc或argv时,最好将void用于参数列表):
int main(void)出于好奇,我复制了您的代码,将所有出现的1000改为ROWS,将所有出现的1000000改为COLS,然后创建了enum { ROWS = 1000, COLS = 10000 }; (从而将问题大小减少了100倍)。我做了一些小改动,以便它可以在我首选的一组编译选项下干净地编译(没什么大不了的:函数前面的static和主数组;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。我运行了这两个程序,并比较了输出文件;输出是相同的。当我在一台大部分空闲的机器上运行这些程序时( Mac,2.3 GHz英特尔酷睿i7,16 GiB 1333 MHz内存,Mac 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循环变成:
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在我看来,代码中只写出一次可怕的表达式的简化是非常有益的。我当然更愿意维护这个程序,而不是原来的程序。
发布于 2012-10-07 03:12:27
你在什么系统上运行?您是否有权访问某种调试器(gdb、visual studio的调试器等)?
这将为我们提供有价值的信息,比如程序崩溃的代码行。此外,内存的大小可能会令人望而却步。
另外,我可以建议您用命名定义替换数字限制吗?
因此:
#define DIM1_SZ 1000
#define DIM2_SZ 1000000只要您想引用数组的维数限制,就可以使用它们。这将有助于避免输入错误。
https://stackoverflow.com/questions/12762944
复制相似问题