alloca()在堆栈上而不是在堆上分配内存,如同的情况一样malloc().所以,当我从例程返回时,内存被释放.所以,实际上这解决了我释放动态分配内存的问题.释放分配的内存malloc()是一个令人头痛的问题,如果不知何故错过会导致各种内存问题.
alloca()尽管有上述特征,为什么不鼓励使用?
灵感来自这个问题.
显然在以下代码中:
#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;
}
Run Code Online (Sandbox Code Playgroud)
使用Visual C++ 10进行编译时使用默认堆栈大小(1兆字节),并在(/ O2)上进行优化,因为程序试图在堆栈上分配1200千字节而发生堆栈溢出.
上面的代码当然有点夸大以显示问题 - 以相当愚蠢的方式使用大量堆栈.然而在实际场景中,堆栈大小可以更小(例如256千字节),并且可能有更多分支具有更小的对象,这将导致总分配大小足以溢出堆栈.
这是没有意义的.最糟糕的情况是700千字节 - 它将是构建一直具有最大总大小的局部变量集的代码路径.在编译期间检测该路径应该不是问题.
因此编译器会生成一个程序,尝试分配比最坏情况更多的内存.根据这个答案, LLVM也是如此.
这可能是编译器的一个缺陷,或者可能有一些真正的理由这样做.我的意思是也许我只是不明白编译器设计中的某些东西可以解释为什么以这种方式进行分配是必要的.
为什么编译器希望程序在最坏的情况下分配比代码需要更多的内存?
c++ stack-overflow compiler-construction memory-management visual-c++
请考虑以下代码:
class Test() {
public:
Test()
{
memset( buffer, 0, sizeof( buffer ) );
}
void Process()
{
printf( buffer );
}
private:
char buffer[1000];
};
int main()
{
Test().Process();
char buffer[1000] = {};
print( buffer );
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我无法推断是否buffer允许在main中重用以前由临时对象占用的内存class Test.根据标准自动存储(3.7.2/1)必须至少持续到块结束.
我找不到强制临时对象使用自动存储的措辞,除了6.6/2,其中描述了一个跳转语句,并说在退出范围[...]时,所有构造对象都会调用析构函数(12.4)具有自动存储持续时间(3.7.2)(命名对象或临时对象),这似乎意味着临时使用自动存储.
临时工需要使用自动存储吗?main上面代码中的局部变量是否允许重用以前由临时占用的内存,还是应该使用不同的存储?