C ++动态整数数组有时会导致崩溃

C++ dynamic array of ints sometimes causes crash

我写了一个简单的代码如下:

void show(const int a[], unsigned elements);

int main()
{
    show(new int[]{1, 2, 3, 45}, 4); //does not work
}

void show(const int a[], unsigned elements)
{
    cout << "{ ";
    for (int i = 0; i < elements; i++)
    {
        cout << a[i];
        if (i != elements - 1)
            cout << ",";
        cout << " ";
    }
    cout << "}";
}

它应该只输出 { 1, 2, 3, 45 }。如果我在括号

中包含一个尺寸
show(new int[4]{1, 2, 3, 45}, 4);

然后就可以了。所以我很自然地假设如果我这样写 new 我必须指定大小(尽管我认为给它一个初始化列表会暗示大小)。但是,奇怪的是,当在 show 函数调用处设置断点并且我 运行 它一步步通过调试器时,程序正确输出所有内容并像它应该的那样在 main 结束时终止。如果我不使用调试器,它要么在输出“{”后崩溃,要么输出整个“{ 1, 2, 3, 45 }”和断言失败“程序:... "Expression: _CrtIsValidHeapPointer(pUserData) ... "

我很想知道为什么会这样。另外,我在 Windows 8.

上使用 Visual Studio

编辑:我是 using namepsace std。请不要评论使用名称空间或如何更好地编写此代码。我只对这个问题的原因感兴趣。

编辑 回复评论中的其他问题。

快速地说,是的,它会 "still" 是一个指针,是的,当您添加 4.

时,它会使用 clang 和 gcc 进行编译。

然而,有一些事情正在发生,我最初的回答是一个简化。问题是您的表达式一开始就不是格式正确的,因此不清楚它应该评估什么或类型应该是什么。考虑

If type is an array type, all dimensions other than the first must be specified as positive integral constant expression (until C++14)converted constant expression of type std::size_t (since C++14), but the first dimension may be any expression convertible to std::size_t.

来源:http://en.cppreference.com/w/cpp/language/new

正如它所说,无论哪种方式,括号中都必须有一个表达式。这使得很难说表达式是否 仍然 计算为指针。一个格式正确的 new 表达式确实会计算为一个指针,无论它有多少维度,即使它的值为零。当我在这里说指针时,我严格来说是指表示,而不是类型。

关键是类型,至少"inside" new,根据你有多少维度是不同的。所以,无论你

new int
new int[6]
new int[12][14]

表示是相同的(指针),但是 new 看到的类型在每种情况下都不同。编译器能够响应 new 中的不同类型(类比函数重载)。特别是,当类型为数组类型时,可以使用包含多个元素的花括号初始化列表来初始化新内存。

我最好的猜测是,由于 VS 在没有表达式的情况下接受括号,它正在为单个 intint[0] 分配内存。在前一种情况下,它错误地允许您将其初始化为数组类型,而在后一种情况下,分配的内存无论如何都不够用。你的 main 然后写了一个堆守卫,它可以在调试模式下捕获这种东西。当在 main 末尾或程序终止时对此进行检查时,您会看到这些症状。输出中的不稳定是由于不同的堆布局或由于输出流中的缓冲。

原回答

您的 new 表达式,如果格式正确,将具有标量类型,这意味着结果是 "single value"。该单个值是一个指向整数的指针,特别是指向您要创建的数组开头的那个。这就是 "dynamic arrays" 在 C++ 中的表示方式。类型系统不 "know" 它们的大小。

您正在尝试使用包含 4 个值的初始化程序列表来初始化此单个指针值。这不应该工作。我不确定这是否应该编译。它肯定没有用 clang 或 gcc 编译,我很惊讶它在 Visual Studio.

中工作