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

标签 c++ arrays memory dynamic 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 }”和断言失败“程序:...”表达式:_CrtIsValidHeapPointer( pUserData) ... "

我很想知道为什么它会这样。另外,我在 Windows 8 上使用 Visual Studio。

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

最佳答案

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

快速地说,是的,它“仍然”是一个指针,是的,当您添加 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 表达式确实会评估为一个指针,无论它有多少维度,即使它的值为零。当我在这里说指针时,我严格来说是指表示,而不是类型。

重点是类型,至少“内部”new,根据您拥有的维度数量而有所不同。所以,无论你是否这样做

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

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

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

原始答案

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

您正在尝试使用包含 4 个值的初始化列表来初始化这个单个指针值。这不应该工作。我不确定这是否应该编译。它当然不能用 clang 或 gcc 编译,我很惊讶它能在 Visual Studio 中运行。

关于C++动态整数数组有时会导致崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30268942/

相关文章:

javascript - 使用重复键连接对象中的 2 个数组

c++ - 错误 C2440 : 'initializing' : cannot convert from 'const wchar_t [9]' to 'LPCSTR'

c++ - 使用 clang++ 3.2 初始化 'vector<string>' 没有匹配的构造函数

c++ - C++ 程序中的奇怪错误 : Removing Printout Breaks Program

c++ - 如何在 Turbo C++ 中创建基于字符的数组?

c - 如何释放指针在内存中的空间?

来自存储在 char 数组中的文件的 C++ 行

java - 如何初始化另一个类中定义的数组?

C++ new 运算符——内存布局

windows - 为什么 Windows 为其系统地址空间保留 1Gb(或 2 Gb)?