1

我正在阅读Use Python for Scientific Computing,并决定自己测试代码。所以 C++ 代码是(稍作修改)

#include <cstdlib>
#include <ctime>
#include <iostream>
#include <cstring>

int main() {
    std::clock_t begin = std::clock();
    double a1[500][500];
    double a2[500][500];
    double a3[500][500];
    memset(a1, 0, 500*500*sizeof(double));
    memset(a2, 0, 500*500*sizeof(double));
    memset(a3, 0, 500*500*sizeof(double));
    int i, j, k;
    for(i = 0; i < 500; i++) {
        for(j = 0; j < 500; j++) {
            for(k = 0; k < 500; k++) {
                a3[i][j] += a1[i][k] * a2[k][j];
            }
        }
    }
    std::clock_t end = std::clock();
    std::cout << (double)(end - begin) / (double)CLOCKS_PER_SEC<<std::endl;
    return 0;
}

这是一个非常简单的代码,但奇怪的是根本没有生成任何输出。不是0,而是什么都没有。我尝试了 VC11 和 MinGW 4.7,但它们都没有产生任何结果。只有for去掉里面的循环,这段代码才会产生输出,也就是0。

如果我在 VS 2012 中调试,则会抛出“堆栈溢出”异常,而如果不在调试模式下则不会发生错误。

这种奇怪行为的原因是什么?


编辑

所以我用new了,这次有一个正常的输出0.83。

尽管如此,我还是觉得奇怪的是没有显示堆栈溢出错误,但程序只是退出而不给出输出。

4

5 回答 5

1

你跑了两件事:

  1. 编译器\环境参数差异。默认堆栈大小(a1、a2 和 a3 在堆栈中分配)因编译器、操作系统而异。因此,在堆栈不足以容纳这些变量的情况下,您会得到堆栈溢出异常
  2. 优化级别的差异(SuvP 得到 0.83 秒):此代码执行时间会因优化而异。编译器可以注意到循环没有做任何特别的事情,只是将其删除。它可以走得更远,意识到memset它们没有用,也可以删除它们。但是如果按原样执行循环,那么在 double 上会有 1.25 亿次操作,这将远远超过仅仅 0.8 秒。

您链接的帖子中的测试从一开始就有缺陷......

于 2013-04-18T08:17:53.390 回答
1

视觉工作室:

您试图在堆栈上放置(提交)6MB,在 x86 和 x64 上,默认保留堆栈大小为 1MB,在安腾上,默认保留堆栈大小为 4MB。你不能承诺比你保留的更多。

在 Visual Studio 中要更改预定义的保留堆栈大小,您应该转到项目属性->链接器->系统->堆栈保留大小,将值设置为 10000000(10MB),您不会有任何问题。

于 2013-04-18T08:22:22.710 回答
1

这绝对是堆栈溢出。在 VS 2008 上,它给了我Unhandled exception at 0x00ef18d7 in Test.exe: 0xC00000FD: Stack overflow.

chkstk.asmtest命令中发生错误:

; Find next lower page and probe
cs20:
        sub     eax, _PAGESIZE_         ; decrease by PAGESIZE
  -->   test    dword ptr [eax],eax     ; probe page.
        jmp     short cs10

_chkstk endp

要解决此问题,请使用new@sarat 提到的分配器分配:

double** a1 = new double*[500];
for(int i = 0; i < 500; ++i)
    a1[i] = new double[500];
于 2013-04-18T08:17:06.947 回答
0

这将导致堆栈溢出。尝试使用 new 而不是本地数组声明。

这应该会有所帮助:如何在 C++ 中使用数组

于 2013-04-18T08:03:36.247 回答
0

如果不在调试模式下,您的代码只是崩溃/冻结,修复堆栈溢出,它将完成。

增加堆栈大小(链接器堆栈选项)。

于 2013-04-18T08:19:15.137 回答