我有一个实现高斯消除的C ++程序。 它在计算部分编译并运行正常,但在它应该告诉计算所花费的时间之前它会崩溃并发生段错误。
#include <iostream>
#include <time.h>
#include <omp.h>
#include <vector>
#include <cstdlib>
using namespace std;
int main()
{
const unsigned int N = 10;
// initialize random seed:
srand (time(NULL));
vector<vector <double> > a(N, vector<double>(N+1)) ;
double buf;
vector<double> x(N);
unsigned int i,j,k;
clock_t t;
t = clock();
double prectime=omp_get_wtime();
//#pragma omp parallel for shared() private() num_threads()
//matrix and right-side vector initialisation
for(i = 0; i < N; i++)
{
for(j = 0; j < N+1; j++)
{
a[i][j]=(1+rand() % 100)/25.0;
//cout << "a[" << i << "][" << j <<"] = " << a[i][j] << endl;
}
}
//there
for(i = 0; i < N -1; i++)
{
for(j = i + 1; j < N; j++)
{
buf=a[i][i]/a[j][i];
//cout << "buf = " << buf << endl;
for (k = 0; k <= N; k++)
{
a[j][k] = a[j][k]*buf - a[i][k];
//cout << "a[" << j << "][" << k <<"] = " << a[j][k] << endl;
}
}
}
// & back again =)
x[N-1] = a[N-1][N]/a[N-1][N-1];
for(i = N-2; i >= 0; i--)
{
buf = 0;
for (j = i+1; j < N; j++)
{
buf += a[i][j] * x[j];
//cout << "buf = " << buf << endl;
}
x[i]=(a[i][N] - buf)/a[i][i];
cout << "x[" << i << "] = " << x[i] << endl;
}
prectime=omp_get_wtime()-prectime;
t=clock()-t;
cout << "The thingy is calculated in " << t << "clicks("<< ((float)t)/CLOCKS_PER_SEC <<" seconds) " << endl;
cout << "Actual time spent is probably " << prectime << "seconds "<< endl;
return 0;
}
用
编译g++ -Wall -fopenmp
,但我认为OpenMP部分现在可以忽略不计(现阶段没有使用)。
我做错了什么?
编辑:如果我将-D_GLIBCXX_DEBUG
添加到已使用的g++
标志,它将编译并运行OK并按预期显示时间。但是,仍然没有帮助我理解为什么和出了什么问题。
答案 0 :(得分:1)
unsigned int i;
for(i = N-2; i >= 0; i--)
i>=0
将永远为真,这是一个无限循环,循环体将使用无效索引I访问a[i][j]
。
更好地将你的循环改为
for(i = N-1; i-- > 0; )
答案 1 :(得分:1)
您将陷入 无限循环 :
for(i = N-2; i >= 0; i--)
因为i
是unsigned int
,所以当你希望它变为-1时,它会溢出(这意味着你错误地索引了你的数组,因为你出界了强>)。结果,您没有达到应该出现时间的程度。一般来说,首先应该确保你的程序是正确的,然后测量它的时间。
尝试将i
设置为int
,而不是unsigned
。
出了什么问题?
由于无限循环,你的程序无限运行,
或
它会崩溃,这将是最有可能发生的情况,因为i
会占用一个非常大的值(系统中最多unsigned int
)并且会访问数组a
无效,因此导致越界访问,这可能会导致分段错误。
通过将i
更改为int
,我们也允许i
为负数,因此它可以获得值-1,这使得此回答中讨论的循环正常,因为它会当i
变为负数时,不要进入循环体。
当处理无符号整数和用于递减计数器的循环时,请始终注意溢出的危险!通常会将计数器的类型更改为unsigned int
,而不是int
,以便摆脱此警告:
警告:有符号和无符号整数表达式之间的比较
但是,你永远不应该忘记,应该谨慎使用递减无符号整数!