C++程序在数组大小过大时停止工作[重复]

tjvv9vkg  于 2024-01-09  发布在  其他
关注(0)|答案(3)|浏览(169)

此问题在此处已有答案

Segmentation fault on large array sizes(7个答案)
10天前关门了。
我在MVC++ 2010中用c++写了一段代码。在里面,程序迭代了一个一维指针数组的元素(双 *)。然而,当我把输入(指针数组的大小)设置得很大,例如15000,并运行程序时,它停止工作并显示一个窗口关闭程序,因为它没有响应!这是什么问题?
下面是构建数组的部分代码:

  1. map<int, double *> CF;
  2. CoefficientMap(CF);
  3. double *T = new double[I * J];
  4. for (int r = 1; r <= I * J; ++r)
  5. T[r] = 100;
  6. SOR(T, CF, 1.8);

字符串
下面是迭代器函数:

  1. void SOR(double *T, map<int, double *> &CF, double w)
  2. {
  3. int iter = 0;
  4. cout << "Stage 2: Solving the linear system of equations using SOR method... ";
  5. const double tol = 0.00001;
  6. double error = tol + 1;
  7. double *TOld = new double[I * J];
  8. for (int i = 1; i <= I * J; ++i)
  9. TOld[i] = 100;
  10. while (abs(error) > tol)
  11. {
  12. ++iter;
  13. for (int i = 1; i <= I * J; ++i)
  14. 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];
  15. error = errorCalc(TOld, T, I * J);
  16. for (int i = 1; i <= I * J; ++i)
  17. TOld[i] = T[i];
  18. if (iter % 100 == 0)
  19. {
  20. cout << endl << endl;
  21. cout << "100 iterations done, please wait..." << endl << "Total accumulative error till this point: " << error << endl;
  22. }
  23. if (iter > 10000)
  24. return;
  25. }
  26. cout << "Done!" << endl << endl;
  27. cout << "Converged after " << iter << " iterations!" << endl;
  28. cout << "Final accumulative error: " << error << endl << endl;
  29. }


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

a7qyws3x

a7qyws3x1#

最可能的解释是,你用完了堆栈空间。简单的解决方法是让数组静态或全局。你也可以从堆中分配new。两者都将数组移出堆栈。
最好的可能是使用智能指针并将其放入堆:

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

字符串
当智能指针变量超出作用域时,这将负责释放内存,无需手动删除。
为了更好的回答,编辑问题以包含代码...
你添加的代码至少在数组索引方面有问题。索引从0开始,然后转到数组大小减一。正确的循环:

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


你在其他循环中也有同样的错误,同样的修复。
替代修复:如果你想从1开始索引(比如,因为你有这样写的伪代码算法,不想改变索引),最简单的是分配一个更大的数组,而不是使用索引0:

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


这样你就可以使用当前的循环了。
这种一个数组元素的缓冲区溢出是很讨厌的,因为通常在分配的内存块的末尾可能有未使用的空间,所以bug可能会完全被忽略,直到你改变数组大小和未使用的空间消失。即使溢出导致堆损坏,它也可能会被忽略,直到你改变代码和损坏的影响改变。所以例如,如果你不走运,添加调试代码可能会隐藏问题。

展开查看全部
svujldwt

svujldwt2#

这听起来像是在堆栈上分配一个普通数组,像这样:

  1. void f()
  2. {
  3. double a[123456];
  4. ...
  5. }

字符串
堆栈的大小是有限的-您应该使用new或(更好)使用std::vector分配。

qpgpyjmq

qpgpyjmq3#

您在堆栈上分配了太多的空间,因此没有足够的内存来满足您的请求。作为替代方案,您可以给予对象静态存储期限,或者您可以使用new将其放在空闲存储区中:

  1. std::unique_ptr<int[]> ptr(new int[size]);

字符串

相关问题