运行时检查失败#4-此函数保留的_alloca内存周围的堆栈区域已损坏?

问题描述

#include <iostream>
#include <malloc.h>

void print_vals(int n)
{
    int *arr = (int *)alloca(n);

    for (int i = 0; i < n; i++)
        arr[i] = i;

    for (int i = 0; i < n; i++)
        std::cout << arr[i] << ' ';

    std::cout << '\n';
}

int main()
{
    print_vals(5);
    print_vals(10);
}

运行此代码时,每次调用都会收到此错误

Run-Time Check Failure #4 - Stack area around _alloca memory reserved by this function is corrupted

enter image description here

我正在使用Visual C ++ 2019,stdc ++ 14和stdc ++ 17都会产生相同的错误

代码有什么问题?

解决方法

我将假设这只是示例代码,因为如果您的意图只是打印数字if (videoOnAd == true) { //do something } else { //do something else } ,那么绝对没有 原因您将为此使用一个数组:-)


对于您的实际问题,0..n函数与alloca一样,分配了许多个字节。如果您将其视为具有多个{ {1}}值(几乎可以肯定大于一个字节)将不能很好地结束。实际上,这在对话框中得到了确认,您会看到大小为10,但每个数组元素占用了四个:

malloc

您需要执行的操作如下:

int

无论如何,我都会避免 Size: 10 Data: <> 00 00 00 00 01 00 00 00 02 00 \_________/ \_________/ \____ arr[0] arr[1] ar ,因为:

  1. 这真的不是标准;和
  2. 如果它无法分配空间,则会有行为异常的烦人习惯,而不是像int *arr = (int*) alloca(n * sizeof(*arr)); // n ints,not bytes. 那样引发异常。

关于最后一点,Linux doco for alloca声明(我强调):

alloca()函数返回一个指向分配空间开头的指针。 如果分配导致堆栈溢出,则程序行为未定义。

如果您想要不需要自己去分配的东西,现代C ++具有智能指针,因此您可以使用类似的东西:

alloca

当该new变量超出范围时,为其分配的内存将自动释放。您可以在原始代码的完整变体中进行尝试:

std::unique_ptr<int[]> arr(new int[n]);

顺便说一句,您会注意到我也更改为使用arr而不是#include <iostream> #include <memory> void print_vals(size_t n) { std::unique_ptr<int[]> arr(new int[n]); for (size_t i = 0; i < n; i++) arr[i] = static_cast<int>(i); for (size_t i = 0; i < n; i++) std::cout << arr[i] << ' '; std::cout << '\n'; } int main() { print_vals(5); print_vals(10); } 作为大小和索引-我认为这更合适。现在,可以肯定的是,它使用了 heap 而不是堆栈,但是根据先前对size_t的评论,这是更安全的方法。

如果您保证一定的大小限制,例如,您可以 使int成功的可能性更高>

alloca

但这实际上并不能保证,因此,如果您打算这样做,则最好还是使用固定的缓冲区,因为您会知道 >最大大小:

alloca

我想提出的另一种解决方案:如果您的意图是尽可能提高效率,则可以使用混合方法。就是说,我的意思是在以下以下使用特定大小的本地缓冲区,并仅在需要时分配内存:

void print_vals(size_t n) {
    if (n >= 100) {
        doSomethingIntelligent();
        return;
    }
    int *arr = (int *)alloca(n * sizeof(*arr));

    ...
}
,

函数alloca()的自变量为 bytes ,因此元素的大小必须乘以元素的数量。

可以这样做:

int *arr = (int *)alloca(sizeof(*arr) * n);