调用函数时出现分段错误

3

在调用Update_Multiplier时出现段错误,gdb调试器显示如下:

程序收到SIGSEGV信号,发生段错误。 0x080b74e8 在Update_Multiplier()中。

double upperbound = 116325;
double objective = 1.1707e+07;
int main()
{
    Update_Multiplier();
}
void Update_Multiplier()
{
    cout << "function 0" << endl;
    // Determine subgradient vectors
    double gra[1000][1000];
    double grb[1000][1000];
    double dumX = 0;
    double stepsize[1000][1000];
    double tuning=2;
    double LRADum[1000][1000];
    double LRBDum[1000][1000];

    cout << "function 1" << endl;
    // update subgradient vectors
    for (int i=1; i<=noOfNodes; i++)
    {
        for (int j=1; j<=noOfNodes; j++)
        {
            if (C[i][j] != 0)
            {
                dumX=0;
                for (int p=1; p<=noOfCommodity; p++)
                {
                    dumX += X[i][j][p];
                }
                gra[i][j]=dumX-U[i][j]*Y[i][j]-Q[i][j];
                grb[i][j]=Q[i][j]-B[i][j]*Y[i][j];
            }
        }
    }

    // update stepsize
    cout << "function 2" << endl;
    for (int i=1; i<=noOfNodes; i++)
    {
        for (int j=1; j<=noOfNodes; j++)
        {
            if (C[i][j] != 0)
            {
                stepsize[i][j]=(tuning*(UpperBound-Objective))/sqrt((gra[i][j]*gra[i][j])*(grb[i][j]*grb[i][j]));
                LRADum[i][j]=LRA[i][j]+stepsize[i][j]*gra[i][j];
                LRA[i][j]=LRADum[i][j];
                LRBDum[i][j]=LRB[i][j]+stepsize[i][j]*grb[i][j];
                LRB[i][j]=LRBDum[i][j];

            }
        }
    }

}

嗯,可能需要40MB的堆栈空间。这是什么平台,并且你知道为堆栈分配了多少内存吗? - CB Bailey
我认为他正在编程那些拥有256位处理器和约200TB内存的电脑,这是其他人都不知道的。 - isekaijin
说实话,它甚至能够到达段错误,这真的很令人惊讶。我看不到coutendlnoOfNodesCnoOfCommodityXUYQBUpperBoundObjectivesqrtLRALRB的声明。此外,在从main调用Update_Multiplier的范围内也没有声明。 - CB Bailey
8个回答

7

我看到你的代码中有两个可疑之处。

首先,你占用了太多的堆栈空间(大约40MB)。
其次,你开始使用数组的索引值是1,而不是应该是0:

for (int i=1; i<=noOfNodes; i++)

将其更改为:

for (int i=0; i<noOfNodes; i++)

哈哈,你比我快。虽然大堆栈是可能的,但我认为这是最有可能的情况。 - Randolpho
循环从1开始的评论也是有效的,但我们不知道noOfNodes的值。如果它小于1,000,那么至少这部分是好的。但是如果它大于1,000呢?看起来函数只是假设noOfNodes永远不会那么大,就分配了1,000 x 1,000的数组。它应该使用noOfNodes的实际值,并从堆中动态分配它们。 - Willis Blackburn
@Willis Blackburn:即使noOfNodes设置为数组中项目的确切数量,从1开始并使用“i<=noOfNodes”也会导致segfault。 - Randolpho
就此而言,我们也不知道B、C、Q、U、X、Y或noOfCommodity是什么。 - Willis Blackburn
Randolpho:这就是为什么我说“如果它小于1,000…” :-) - Willis Blackburn

4

猜测你遇到了堆栈溢出!在堆栈上创建巨大的数组是不可靠的。你需要动态或静态地创建它们。


3

你在哪里定义了noOfNodes?它的初始值是什么?或者,你是从控制台中读取的吗?如果它没有被初始化,那么它可能包含垃圾数据--这可能会解释导致程序崩溃的原因。


2

由于你正在分配五个一百万个八字节双精度浮点数的数组,因此你需要至少40兆字节的堆栈来运行此函数。

将函数更改为使用new从堆中分配双精度数组。


+1 是的,它大约有40MB。我在帖子中最开始提到它只有约5MB大小 :) - Khaled Alshaya

1
你应该给我们整个代码,例如 noOfNodes 在任何地方都没有定义。
只是猜测:你可能会溢出 C,因为你的索引(i 和 j)从 1 到 noOfNodes?

0

首先,Neil所说的是正确的。

其次,C和C++的数组从索引零开始。如果您声明

int a[100]; // 100 elements, from zeroth to ninety-ninth.

那么它的元素就是 a[0]a[1] ... a[99]


0

我在给出的代码中没有发现任何问题,但是:如果 noOfNodes 是 1000,则可能存在一个 off-by-one 错误。

请记住,数组是从 0 开始索引的,因此您必须访问索引 0 到 999,而不是像您正在做的那样访问索引 1 到 1000。


-1

我也遇到了这个问题,我的函数返回了std::string,现在我只需要引用和返回类型void就可以了:

void readOnDicoFile(std::ifstream file/*If you have "using namespace std;" instruction, put ifstream, not std::ifstream (you can put both)*/)

并且在之前:

std::string readOnDicoFile(std::string fileName/*If you have "using namespace std;" instruction, put ifstream, not std::ifstream (you can put both)*/)        

1
这与所问的问题有什么关系? - user1781290

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接