为什么c++程序要为局部变量分配比在最坏情况下需要的更多的内存?
visual Why would a C++ program allocate more memory for local variables than it would need in the worst case?
受到这个问题的启发。
显然在以下代码中:
#include <Windows.h>
int _tmain(int argc, _TCHAR* argv[])
{
if( GetTickCount() > 1 ) {
char buffer[500 * 1024];
SecureZeroMemory( buffer, sizeof( buffer ) );
} else {
char buffer[700 * 1024];
SecureZeroMemory( buffer, sizeof( buffer ) );
}
return 0;
}
在Visual c++ 10 (/O2)上使用默认堆栈大小(1兆字节)编译时,由于程序试图在堆栈上分配1200千字节,因此会发生堆栈溢出。
上面的代码当然稍微夸张了一下,以显示这个问题——以一种相当愚蠢的方式使用了大量的堆栈。然而,在实际场景中,堆栈大小可能更小(如256千字节),并且可能有更多带有较小对象的分支,这将导致总分配大小足以溢出堆栈。这没有意义。最坏的情况是700千字节——它将是构建局部变量集的代码路径,该代码路径在整个过程中具有最大的总大小。在编译过程中检测该路径应该不成问题。
编译器生成的程序会尝试分配比最坏情况更多的内存。根据这个答案,LLVM也做同样的事情。
这可能是编译器的缺陷,或者可能有一些真正的原因这样做。我的意思是,也许我只是不理解编译器设计中的一些东西,这些东西会解释为什么这样做分配是必要的。
在最坏的情况下,为什么编译器希望程序分配比代码所需更多的内存?
我只能推测这个优化被编译器设计者认为太不重要了。或者,可能有一些微妙的安全原因。
顺便说一句,在Windows上,当线程开始执行时,堆栈是保留整个的,但是是根据需要提交的,所以即使你保留了一个大的堆栈,你也不会真正花费太多的"实际"内存。
在32位系统上,保留一个大的堆栈可能是一个问题,在32位系统上,拥有大量的线程可能会占用可用的地址空间,而不会真正提交太多内存。在64位,你是黄金。这可能取决于您对securezerommemory的使用。试着用常规的zerommemory替换它,看看会发生什么——MSDN页面本质上表明SZM有一些超出其签名所暗示的额外语义,它们可能是bug的原因。
在ideone上使用GCC 4.5.1编译时,下面的代码将两个数组放在同一个地址:
#include <iostream>
int main()
{
int x;
std::cin >> x;
if (x % 2 == 0)
{
char buffer[500 * 1024];
std::cout << static_cast<void*>(buffer) << std::endl;
}
if (x % 3 == 0)
{
char buffer[700 * 1024];
std::cout << static_cast<void*>(buffer) << std::endl;
}
}
输入:6
输出:0 xbf8e9b1c
0 xbf8e9b1c
答案可能是"使用另一个编译器",如果你想要这种优化。
操作系统分页和字节对齐可能是一个因素。此外,内务管理可能会使用额外的堆栈以及调用该函数内的其他函数所需的空间。
相关文章:
- 如何在不等待检索的情况下获取C++中的内存位置?
- 如何在多写入器情况下对文件支持的共享内存中的大页面出错
- 为什么它在不分配内存的情况下工作正常
- 我是否访问了已释放的内存,或者在这种情况下DrMemory报告不正确?
- 在没有任何锁的情况下加入另一个线程后是否需要内存围栏?
- 传递链表而不在C++内存泄漏的情况下
- 如何在不使用 "new" 关键字的情况下解除分配创建的对象的内存?
- 在这种特殊情况下,我是否需要在共享内存中使用原子类型
- C++ 在不释放内存的情况下调用析构函数
- 在这种情况下,我必须删除内存吗?
- Cython:如何在不需要 GIL 的情况下从 numpy 内存视图转到矢量[对[双,双]]?
- 在不放置新运算符的情况下,在预分配的内存上使用虚函数初始化对象 - 这可能吗?如果没有,为什么
- 变量如何在不创建对象的情况下获得内存
- 如何在没有动态内存分配(堆)的情况下为可变大小数组(矢量)定义安全容器或视图
- 如何在<N>不发生内存泄漏的情况下同时(线程安全)填充 c++11 std::map<std::string,std::bitset*>?
- 我可以在没有任何锁的情况下从不同的线程读取内存缓冲区吗?
- 是否可以在不分配内存或复制数据的情况下构造对象?
- 如何在不导致内存泄漏的情况下将数组分配给结构内的指针
- 在这种情况下,如何释放内存?
- 在这种情况下内存泄漏?反复使用新关键字