有没有办法检查是否在堆栈/堆上创建了可变长度数组?

Is there a way to check if variable length arrays are created on stack / heap?

据我了解,以下代码生成可变长度数组(通过 C++ 的非标准扩展)。

int main() 
{
    int valone = rand();
    int valtwo = rand();
    int array[valone][valtwo];
    // Printing size
    cout << sizeof(array) << endl;
}

有什么方法可以检查它是在堆栈还是堆上生成的?维基百科描述 heregcc 在堆栈中生成相同的内容,但是当我尝试上面的代码时,大多数时候,数组大小似乎太大而无法放入堆栈,但它从不抱怨。

注意:此代码仅适用于 gcc 和 clang,不适用于 visual studio

首先,我假设您知道使用 malloc 或 new 在堆中分配的任何内存块在整个程序中都会继续其生命周期,除非显式解除分配。因此我们可以得出结论,如果一个变长数组只存在于它的范围内,而不存在于程序的生命周期内,那么它很可能分配在堆栈中。

我不知道是否存在在堆中分配了一块内存但表现得好像它是堆栈成员的情况。最好查看汇编代码。这样的实现可能会在幕后使用动态分配functions/syscalls。

如果它看起来像鸭子,走路像鸭子,说话像鸭子,那么可以安全地假设它是鸭子(大部分时间)。

这可能是一个棘手的问题,我已经尝试过

#include "iostream"

int Stack_or_heap(void* ptr)
{
 int dummy;
 return ptr > &dummy;
}

int main(int argc, char** argv)
{
   int* i = new int();
   int x, y, z;
   std::cout << Stack_or_heap(&x) << Stack_or_heap(&y) << Stack_or_heap(&z) << Stack_or_heap(i);
}

the array size seems too big to fit into stack, but it never complains.

"never complains",我想你的意思是程序不会崩溃。

您永远不会触及您分配的内存,编译器足够聪明地证明了这一点并且没有分配任何东西。

让我们获取变量的地址,并将其发送到别处定义的函数:

int array[valone][valtwo] = {};
cout << &array << endl;

现在,编译器不太确定数组从未被访问过。那是因为它不能进入​​在另一个翻译单元中实现的流操作符。也许操作员会取消对指针的引用;我们必须确保数组存在。

Segfault 在我第一次尝试时使该程序崩溃。堆栈溢出。


我想这种碰撞测试是一种测试 VLA 是否在堆栈上的方法。

Mikhail 在评论中提出的将自动变量的相邻性与 VLA 进行比较的建议是一个不错的依赖于平台的想法,但它只有在分配足够小的 VLA 不会使程序崩溃时才有效。