“程序接收信号SIGSEGV,分段故障。”

时间:2013-09-28 17:02:25

标签: c++

我正在尝试编写一个计算两个大型密集矩阵的乘积的程序。当我使用尺寸为200 x 200的矩阵时,程序工作正常,但是当我转到300 x 300时,我得到一个弹出窗口,说“Assignment2.exe已停止工作......”我运行了调试器,我得到了这个错误消息:“程序收到信号SIGSEGV,分段错误。”

我知道显而易见的罪魁祸首是矩阵的大小太大,但我想知道是否有任何方法可以优化我的程序,以便它可以处理更大的矩阵(不更改函数原型,因为这些是设置的在石头上进行任务)。在MATLAB中,我能够处理比这更大的矩阵。我感谢您的帮助。谢谢!

这是我的代码:

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <random>

using namespace std;

int matrix_multiply(int n1, int n2, int n3, double *a, double *b, double *c);
int matrix_fill_random(int n1, int n2, double *a);
int matrix_print(int n1, int n2, double *a);


int matrix_multiply(int n1, int n2, int n3, double *a, double *b, double *c)
{
    int i;
    int j;
    int k;

    for (i=0;i<n1;i++) {
        for (j=0;j<n3;j++) {
            *(c+(i*n3)+j) = 0;
            for (k=0;k<n2;k++) {

                *(c+(i*n3)+j) += (*(a+(i*n2)+k) * (*(b+(k*n3)+j)));
            }
        }
    }
    return 0;
}

int matrix_fill_random(int n1, int n2, double *a)
{
    int i;
    for (i=0;i<(n1*n2);i++) {
        *(a+i) = rand() % 20001 - 10000;
        *(a+i) /= 10000;
    }
    return 0;
}

int matrix_print(int n1, int n2, double *a)
{
    int i;
    int j;

    cout << "\n" << endl;

    for (i=0;i<n1;i++) {
        for (j=0;j<n2;j++) {
            if (*(a+(i*n2)+j) >= 0) {
                cout << " ";
            }
            cout << *(a+(i*n2)+j) << "\t";
        }
        cout << " " << endl;
    }
    return 0;
}

int main() {

    int numRowsA;
    int numColsA;
    int numColsB;
    int numIterations;
    int i;
    srand((unsigned int)time(0));

    cout << "Please enter in the number of rows for Matrix A: ";
    cin >> numRowsA;
    cout << "Please enter in the number of columns for Matrix A: ";
    cin >> numColsA;
    cout << "Please enter in the number of columns for Matrix B: ";
    cin >> numColsB;
    cout << "Please enter in the number of iterations for repeating the multiplication: ";
    cin >> numIterations;

    double A[numRowsA][numColsA];
    double B[numColsA][numColsB];
    double C[numRowsA][numColsB];

    matrix_fill_random(numRowsA,numColsA,(&A[0][0]));
    matrix_fill_random(numColsA,numColsB,(&B[0][0]));

    clock_t beforeMult;
    clock_t afterMult;
    clock_t ticks;
    float seconds;
    float secondsPerIteration;

    beforeMult = clock();

    for (i=0;i<numIterations;i++){
        matrix_multiply(numRowsA,numColsA,numColsB,(&A[0][0]),(&B[0][0]),(&C[0][0]));
        delete C;
    }

    afterMult = clock();

    ticks = afterMult - beforeMult;
    seconds = (float(ticks))/numIterations;
    secondsPerIteration = seconds/CLOCKS_PER_SEC;

    cout << "The number of total clock ticks is: " << ticks << endl;
    cout << "The number of ticks per multiplication is: " << seconds << endl;
    cout << "The number of seconds per multiplication is: "  << secondsPerIteration << endl;

    delete A;
    delete B;
    delete C;
}

2 个答案:

答案 0 :(得分:2)

这样做是完全错误的:

delete A;
delete B;
delete C;

由于ABC在此创建:

double A[numRowsA][numColsA];
double B[numColsA][numColsB];
double C[numRowsA][numColsB];

并且这些行中没有new。如果您没有致电new来创建某些内容,则不应使用delete。并且 IF 使用new创建二维数组,您很可能需要使用循环为每行分配列,然后反过来使用它来删除它 - 在删除数组时使用delete []

上面的代码也不符合C ++标准,因为标准C ++中任何数组的大小必须是编译时常量。您正在从用户那里读取大小,因此大小显然不是编译时常量。使用大量的列和行可能会导致在堆栈上分配空间时出现问题,即使编译器允许它也是如此。大多数系统的默认值大约为1-4MB的堆栈大小(因此最多可以达到500k左右的最大值)。一旦你使用了它,它就是“游戏结束”,那时你无法做任何事情来恢复。所以最好避免耗尽堆栈。这带来了循环的想法,以分配适当的内存量。但是,我建议您使用std::vector而不是原始指针或数组,如下所示:

std::vector<std::vector <double> > A;

A.resize(numrowsa);
for(int i = 0; i < numrowsa; i++)
{
    A[i].resize(numcolsa); 
}

同样适用于B和C.

答案 1 :(得分:0)

使用new运算符为我工作,如下面的代码所示:

double *A = new double[numRowsA*numColsA];
double *B = new double[numColsA*numColsB];
double *C = new double[numRowsA*numColsB];