web-dev-qa-db-ja.com

このエラーの意味: `somefile.c:200:エラー:1032バイトのフレームサイズが1024バイトより大きい`

作成中に、次の行に沿ってエラーが表示されます。

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

行番号は、次のようなシグネチャを持つc関数の右中括弧を指します。

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

関数はいくつかのものをバッファに出力します。

このタイプのエラーが一般的に何を意味するか誰でも知っていますか?

そのルーチンには、スタック割り当てされている大きなバッファがあると思います。これにより、その関数のスタックフレームが1024バイトを超える可能性があります。これは、ビルドしているアーキテクチャのコンパイラーによる制限のようです。考えられる解決策としては、コンパイラフラグを渡して警告を緩和する、スタックサイズの上限を拡張する、またはバッファを動的に割り当てるなどがあります。

34
fbrereto

この警告に関するGCCのドキュメントは次のとおりです。

STACK_CHECK_MAX_FRAME_SIZE

スタックフレームの最大サイズ(バイト単位)。 GNU CCは、非リーフ関数でプローブ命令を生成して、少なくともこのバイト数のスタックが使用可能であることを確認します。スタックフレームがこのサイズより大きい場合、スタックチェックは信頼できなくなり、= GNU CCは警告を発行します。デフォルトは、GNU CCがほとんどのシステムで1つの命令しか生成しないように選択されています。通常、このデフォルト値は変更しないでください。大きい。

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

-Wframe-larger-than

警告は-Wframe-larger-thanによって生成されます。 GCC 7のman gccによると:

関数フレームのサイズがlenバイトより大きい場合に警告します。スタックフレームサイズを決定するために行われる計算は概算であり、保守的ではありません。警告が出なくても、実際の要件はlenよりも多少大きい場合があります。さらに、 "alloca"、可変長配列、または関連する構成要素を介して割り当てられたスペースは、警告を発行するかどうかを決定するときにコンパイラーに含まれません。

最小限の例

main.c

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

そして:

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

なぜこれが存在するのか

オペレーティングシステムはスタックサイズを制限する必要があります。そうしないと、ヒープ/ mmapsに達するまでサイズが大きくなり、すべてが予期せず破損します。

Linuxは、プログラムがその最大スタックサイズを超えようとすると信号を送信します。

-Wframe-larger-than=は、関数のローカル変数(スタックに配置されている)を小さく保つことで、スタックのオーバーフローを防ぐのに役立つ方法です。

ただし、再帰関数を呼び出すときに問題が発生する可能性が高く、すべてが再帰回数に起因するため、コンパイル時間の保証はありません。

解決策は、大きな配列をローカル変数として使用する代わりに、mallocを使用してメモリを割り当てることです。これは、mmapメモリを使用することになります。

スタックとmallocメモリの主な違いは、スタックが連続している必要があることです。これは、単純な場合、優れたメモリパッキング効率につながりますが、mallocには複雑なヒューリスティックが必要です。以下も参照してください。