1

在 c++ 中,在分配内存时会发生 bad_alloc,或者至少这是我所理解的,但是现在我在从数组中读取内存时遇到了这个错误。我创建数组:

int * possible = new int[ suma ];

然后我得到了两个循环,在那里我访问了整个数组:

for( int i = 0; i < n - 1; i++ ){
    int rowWidth = (i - 1) < 0 ? 0 : permutationsNumber[i];
    for( int j = 0; j < permutationsNumber[i]; j++ ){
        possible[i * rowWidth + j ] = j;
    }
}

for( int i = 0; i < n - 1; i++ ){
    int rowWidth = (i - 1) < 0 ? 0 : permutationsNumber[i];
    for( int j = 0; j < permutationsNumber[i]; j++ ){
        std::cout << possible[i * rowWidth + j ] << "\n";
}

在第二行std::cout << possible[i * rowWidth + j ] << "\n";中,我得到了错误。

我在 Windows 上编译代码,尝试使用 3 台不同的 Windows 8 和 7 机器,使用 VS 2010、2012 和 2013 并得到相同的错误。

当我在 Mac 上编译代码时没有错误,使用 compileonline 也是如此

我认为不那么重要的变量值是:

n = 4;
permutationsNumber = {4, 12, 24};
suma = 40;
4

2 回答 2

2

你的理解bad_alloc有点不正确。bad_alloc当 new 操作符无法分配请求的内存量时,它会抛出。如果您将非常大的值发送到new.

例如,如果suma不进行初始化,可能会发生这种情况。

您应该在调试器(在 gdb 中)中打开首次异常处理,catch throw并验证抛出异常的位置以及程序请求的内存量。

您可能会观察到无效的内存引用。您可以替换要使用的代码std::vector并使用该at()方法来访问元素。如果您错误地访问了超出范围的元素,这将引发异常。

或者,添加这样的断言:

#include<cassert>
...
const int idx = i * rowWidth + j;
assert(idx >= 0);
assert(idx < suma);
possible[idx] = j;

如果断言触发(它可能会触发),您现在将确认您的数组太小或您的索引无效。

于 2014-04-07T03:31:07.143 回答
1

您正在破坏程序的堆。第一对for循环的最后一遍将写入possible[71],但它实际上只有 40 个插槽。

它不一定会立即崩溃的原因是内存保护通常在整个页面上运行(x86 上为 4KB)。除非您的缓冲区恰好落在页面末尾,否则数组末尾之后的许多位置可能会落在与数组末尾相同的(有效)页面上,因此写入它们可能不会立即导致错误.

在 Windows 上,您可以使用gflags 实用程序强制所有堆分配在页面末尾结束,这样溢出将立即导致页面错误。

于 2014-04-07T04:05:54.077 回答