What does this error mean: `somefile.c:200: error:

2020-05-21 09:35发布

问题:

During a make, I'm seeing an error along the lines of:

cc1: warnings being treated as errors
somefile.c:200: error: the frame size of 1032 bytes is larger than 1024 bytes

The line number points to the closing brace of a c function that has a signature like this:

void trace(SomeEnum1 p1, SomeEnum2 p2, char* format, ...) {
    char strBuffer[1024];
    ...

The function prints some stuff into the buffer.

Anyone know what this type of error means in general?

回答1:

I'm guessing there's some large buffer in that routine that is stack-allocated; this is likely causing the stack frame of that function to exceed 1024 bytes, which seems to be some compiler-enforced limit for the architecture upon which you are building. Possible solutions would include passing a compiler flag to relax the warning, expand the upper limit of the stack size, or dynamically allocating the buffer.



回答2:

Here is the GCC documentation referring to this warning:

STACK_CHECK_MAX_FRAME_SIZE

The maximum size of a stack frame, in bytes. GNU CC will generate probe instructions in non-leaf functions to ensure at least this many bytes of stack are available. If a stack frame is larger than this size, stack checking will not be reliable and GNU CC will issue a warning. The default is chosen so that GNU CC only generates one instruction on most systems. You should normally not change the default value of this macro.

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



回答3:

-Wframe-larger-than

The warning is generated by -Wframe-larger-than. man gcc of GCC 7 says:

Warn if the size of a function frame is larger than len bytes. The computation done to determine the stack frame size is approximate and not conservative. The actual requirements may be somewhat greater than len even if you do not get a warning. In addition, any space allocated via "alloca", variable-length arrays, or related constructs is not included by the compiler when determining whether or not to issue a warning.

Minimal example

main.c

int main(void) {
    char s[1024];
    return 0;
}

and:

$ 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.

Why this exists

Operating systems must limit the stack size, otherwise it would grow until it reaches the heap / mmaps and everything would break unpredictably.

Linux sends a signal if the program tries to grow beyond that maximum stack size.

-Wframe-larger-than= is a way to help to prevent the stack from overflowing, by keeping function local variables (which are placed on the stack) small.

There is no compile time guarantee however, since the problem is likely to happen when calling recursive functions, and it all comes down to how many times it recurses.

The solution is to allocate memory with malloc instead of using large arrays as local variables. This ends up using mmap memory.

The key difference between the stack and malloc memory is that the stack must be contiguous, which is simple leads to great memory packing efficiency, while malloc requires complex heuristics. See also:

  • What is the function of the push / pop instructions used on registers in x86 assembly?
  • https://unix.stackexchange.com/questions/145557/how-does-stack-allocation-work-in-linux/239323#239323