这个错误是什么意思:`somefile.c:200:错误:1032字节的帧大小大于1024字节`?

Pie*_*tte 27 c gcc compiler-errors makefile build

在制作过程中,我发现了一个错误:

cc1: warnings being treated as errors
somefile.c:200: error: the frame size of 1032 bytes is larger than 1024 bytes
Run Code Online (Sandbox Code Playgroud)

行号指向ac函数的右括号,其具有如下签名:

void trace(SomeEnum1 p1, SomeEnum2 p2, char* format, ...) {
    char strBuffer[1024];
    ...
Run Code Online (Sandbox Code Playgroud)

该函数将一些内容打印到缓冲区中.

任何人都知道这种错误通常意味着什么?

fbr*_*eto 35

我猜这个例程中有一些大的缓冲区是堆栈分配的; 这可能导致该函数的堆栈帧超过1024个字节,这似乎是您正在构建的体系结构的一些编译器强制限制.可能的解决方案包括传递编译器标志以放松警告,扩展堆栈大小的上限或动态分配缓冲区.

  • 实际上,首先发生的是分配1024大小的缓冲区. (2认同)
  • 男人我也会说这个,但我想先看看这个功能.:) (2认同)

Pie*_*tte 13

以下是参考此警告的GCC文档:

STACK_CHECK_MAX_FRAME_SIZE

堆栈帧的最大大小(以字节为单位).GNU CC将在非叶函数中生成探测指令,以确保至少有这么多字节的堆栈可用.如果堆栈帧大于此大小,则堆栈检查将不可靠,GNU CC将发出警告.选择默认值以便GNU CC仅在大多数系统上生成一条指令.通常不应更改此宏的默认值.

来自http://gcc.gnu.org/onlinedocs/gcc-2.95.3/gcc_17.html#SEC214

  • 堆栈帧是编译器放置自动变量的位置.如果你有任何局部变量,那么strBuffer你将溢出1024限制.尝试减小strBuffer的大小,为其他局部变量腾出空间.编译器也可以使用堆栈帧中的一些空间供自己使用,通常保存返回地址和硬件寄存器. (2认同)

Cir*_*四事件 7

-Wframe-larger-than

警告由生成-Wframe-larger-than.man gccGCC 7的说法是:

如果函数帧的大小大于len个字节,则发出警告.用于确定堆栈帧大小的计算是近似的而不是保守的.即使您没有收到警告,实际要求也可能略高于len.此外,在确定是否发出警告时,编译器不包括通过"alloca",可变长度数组或相关构造分配的任何空间.

最小的例子

int main(void) {
    char s[1024];
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

和:

$ gcc -std=c99 -O0 -Wframe-larger-than=1 main.c
main.c: In function ‘main’:
main.c:4:1: warning: the frame size of 1040 bytes is larger than 1 bytes [-Wframe-larger-than=]
 }
 ^
$ gcc -std=c99 -O0 -Wframe-larger-than=2048 main.c
# No warning.
Run Code Online (Sandbox Code Playgroud)

为什么会这样

操作系统必须限制堆栈大小,否则它会一直增长直到达到堆/ mmaps并且一切都会无法预测地破坏.

如果程序试图超出最大堆栈大小,Linux会发送信号.

-Wframe-larger-than= 是一种通过保持函数局部变量(放置在堆栈上)较小来帮助防止堆栈溢出的方法.

然而,没有编译时保证,因为在调用递归函数时可能会发生问题,而这一切都归结为它的递归次数.

解决方案是分配内存malloc而不是使用大型数组作为局部变量.这最终使用mmap内存.

堆栈和malloc内存之间的关键区别在于堆栈必须是连续的,这很简单,可以提高内存打包效率,同时malloc需要复杂的启发式算法.也可以看看: