堆栈帧是否已分配并取消分配范围?

时间:2017-02-05 10:04:11

标签: c++ stack

previous question here开始,我一直在查看VS2015代码分析的输出,并在函数中查看高堆栈使用警告,可以简化如下;

class base
{
public:
   virtual void Process();
   Buffer[10000];
};

class derived1 : public base
{
public:
   void Process();
}

class derived2 : public base
{
public:
   void Process();
}

void MyFunc(int x)
{
   switch(x)
   {
     case 0:
     {
       derived1 x;
       x.Process();
     } break;
     case 1:
     {
       derived2 y;
       y.Process();
     } break;
   }
}

分析警告我,我在MyFunc中使用了20,000字节的堆栈。是这种情况,因为所有堆栈变量都在函数入口处分配并在函数出口处解除分配,而不是在它们构造和使用范围进行破坏时?只是好奇(但不是很好奇,可以通过汇编输出;))related question这里并没有给我正在寻找的答案。

1 个答案:

答案 0 :(得分:1)

堆栈帧分配由编译器自行决定。大多数编译器不会尝试使用大变量隔离本地作用域,但大多数编译器确实提供了<%@page import="com.google.zxing.client.j2se.MatrixToImageWriter"%> <%@page contentType="text/html" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>JSP Page</title> </head> <h1>Hello World!</h1> <%@page language='java'%> <%@page import="java.io.*,java.util.*,java.util.Hashtable,javax.imageio.*,com.google.zxing.*,com.google.zxing.client.*,com.google.zxing.common.*,com.google.zxing.qrcode.decoder.*"%> <% String qrCodeData = "Hello World!"; String filePath = "QRCode.png"; String charset = "UTF-8"; // or "ISO-8859-1" Hashtable hintMap = new Hashtable(); hintMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L); createQRCode(qrCodeData, filePath, charset, hintMap, 200, 200); out.println("QR Code image created successfully!"); %> <%! public void createQRCode(String qrCodeData, String filePath, String charset,Hashtable hintMap, int qrCodeheight, int qrCodewidth) throws WriterException, IOException { BitMatrix matrix = new MultiFormatWriter().encode( new String(qrCodeData.getBytes(charset), charset), BarcodeFormat.QR_CODE, qrCodewidth, qrCodeheight,hintMap); MatrixToImageWriter.writeToFile(matrix, filePath.substring(filePath .lastIndexOf('.') + 1), new File(filePath)); } %> </body> </html> 或C99 VLA等设备,它们动态扩展现有的堆栈帧。所以建筑问题不太可能发挥作用;这纯粹是实施细节的问题。

您可以将局部作用域括在lambda表达式中,以鼓励编译器提供这样的隔离:

alloca

但是,没有任何保证。

您可以使用godbolt.org在线编译器查看此类示例的机器代码反汇编。看起来这个技巧适用于GCC,但是在Clang上它只适用于优化 switch(x) { case 0: []{ derived1 x; x.Process(); }(); break; case 1: []{ derived2 y; y.Process(); }(); break; } 或更少,而在英特尔的编译器上它只适用于-O1