当数组大小太大时,C++ 程序将停止工作

问题描述 投票:0回答:3

我在 MVC++ 2010 中用 C++ 编写了一段代码。在其中,程序迭代一维指针数组(双 *)的元素。但是,当我将输入(指针数组的大小)设置得非常大(例如 15000)并运行该程序时,它会停止工作并显示一个窗口来关闭程序,因为它没有响应!有什么问题吗?

这是构建我正在讨论的数组的代码的一部分:

map<int, double *> CF;
CoefficientMap(CF);

double *T = new double[I * J];
for (int r = 1; r <= I * J; ++r)
    T[r] = 100;
SOR(T, CF, 1.8);

这是迭代器函数:

void SOR(double *T, map<int, double *> &CF, double w)
    {
    int iter = 0;
    cout << "Stage 2: Solving the linear system of equations using SOR method... ";

    const double tol = 0.00001;
    double error = tol + 1;
    
    double *TOld = new double[I * J];
    for (int i = 1; i <= I * J; ++i)
        TOld[i] = 100;
    
    while (abs(error) > tol)
    {
        ++iter;
        for (int i = 1; i <= I * J; ++i)
            T[i] = (CF[i][0] + CF[i][1] * T[i + 1] + CF[i][2] * T[i + J] + CF[i][3] * T[i - J] + CF[i][4] * T[i - 1]) * w + (1 - w) * T[i];

        error = errorCalc(TOld, T, I * J);
        
        for (int i = 1; i <= I * J; ++i)
            TOld[i] = T[i];
        
        if (iter % 100 == 0)
        {
            cout << endl << endl;
            cout << "100 iterations done, please wait..." << endl << "Total accumulative error till this point: " << error << endl;
        }

        if (iter > 10000)
            return;
    }
    
    cout << "Done!" << endl << endl;
    cout << "Converged after " << iter << " iterations!" << endl;
    cout << "Final accumulative error: " << error << endl << endl;
}

现在,当 (I * J) 变得足够大(例如 15000)时,程序将停止工作!

c++ visual-c++ visual-c++-2010
3个回答
3
投票

最可能的解释是,堆栈空间不足。简单的解决方法是将数组设为静态或全局。您还可以使用堆中的

new
来分配它。两者都将数组移出堆栈。

最好的可能是使用智能指针并将其放入堆中:

std::unique_ptr<double[]> arrayOfDoubles(new double[size]);

当智能指针变量超出范围时,这将负责释放内存,无需手动删除。

为了获得更好的答案,请编辑问题以包含代码...


您添加的代码至少在数组索引方面存在问题。索引从 0 开始,到数组大小减一。正确循环:

double *T = new double[I * J];
for (int r = 0; r < I * J; ++r)
    T[r] = 100;

您在其他循环中也有同样的错误,同样的修复。

替代修复:如果您想从 1 开始索引(例如,因为您有这样编写的伪代码算法并且不想更改索引),最简单的方法是分配一个更大的数组而不使用索引 0:

double *T = new double[I * J + 1];

这样您就可以使用当前的循环了。


这种由一个数组元素造成的缓冲区溢出是令人讨厌的,因为在分配的内存块的末尾通常可能有未使用的空间,因此在更改数组大小并且未使用的空间消失之前,错误可能会完全被忽视。即使溢出导致堆损坏,也可能会被忽视,直到您更改代码并且损坏的影响发生变化。因此,如果您运气不好,添加调试代码可能会隐藏问题。


2
投票

听起来您正在堆栈上分配一个普通数组,如下所示:

void f()
{
    double a[123456];
    ...
}

堆栈的大小有限 - 您应该使用

new
进行分配或(更好)使用
std::vector


2
投票

您在堆栈上分配了太多空间,因此没有足够的内存来满足您的请求。作为替代方案,您可以给予对象静态存储持续时间,或者您可以使用

new
:

将其放在免费存储中
std::unique_ptr<int[]> ptr(new int[size]);
© www.soinside.com 2019 - 2024. All rights reserved.