c – 如何强制MSVC编译器忽略大型临时对象的堆栈分配?

此问题与
this one或其他类似问题不重复.这个问题是关于在初始化和使用它之后清除结构.

更新

在阅读了您的前几条评论之后,我想澄清一下我的问题:

>如何强制MSVC编译器忽略大堆栈分配?

我已经更新了标题,文字和下面的代码来澄清这一点.

我最近开始使用/ GS,/ sdl和/ analyze编译器选项编译我的项目. (Microsoft Visual C 2015)使用这些选项,编译器会正确警告可疑的代码构造.但是,我遇到了一些警告,我一直认为这是一种很好的C风格.

请查看以下示例代码:

struct my_struct {
    char  large_member[64000];
};

void do_something_else(my_struct & ms)
{
    // the intent of the next line is to "clear" the ms object
    ms = {};  // <-- here the compiler claims the large stack allocation

   // ... do some more work with ms
}

my_struct oh_my = {}; // construction, apparently no large stack allocation

int main()
{ 
    // ...
    // do something with the oh_my object
    // 

    do_something_else(oh_my);
}

我被告知清除结构的标准C方式如下:

ms = {};

使用/ analyze选项,编译器会以下列方式警告此情况(示例):

C:\Dev\MDS\Proj\MDSCPV\Vaps_Common_lib\camber_radar.cpp:162: warning: C6262: Function uses ‘144400’ bytes of stack: exceeds /analyze:stacksize ‘16384’.. This allocation was for a compiler-generated temporary for ‘struct BitmapBuffer’ at line 162. Consider moving some data to heap.

我认为会发生以下情况:

>在堆栈上构造临时对象
>临时对象被复制到对象变量

我希望看到像那里发生的默认初始化.在我看来,编译器应该能够优化堆栈分配.但显然(根据警告)编译器不会这样做.
我的问题是:如何强制编译器忽略堆栈分配?
我现在开始用以下代码替换这些地方:

std::memset(&ms, 0, sizeof(ms));

最佳答案 由于my_struct很容易复制,编译器应该能够放置一个memset调用而不是创建一个临时调用,然后分配它,但它不是必需的.

Placement new表达式将解决您的问题:它使用提供的构造函数在预分配的地址构造对象.例如,new(& ms)my_struct {}给出与ms = {}相同的语义.如果my_struct有一个非平凡的析构函数,则显式调用ms.~my_struct()必须在placement new之前.供参考:new expression

我建议不要以正常的方式使用这种技术.它是一种’黑魔法’低级别C级.好的编译器应该使用memset进行优化.

顺便说一下,oh_my全局变量不会在堆栈上分配临时值,因为它是在编译时初始化的常量.

点赞