从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这里并没有给我正在寻找的答案。
答案 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
。