2011-12-26 10 views
3

非再帰的な関数では、大きなデータ型をスタックに置くことは一般的に問題ありませんか?大きなオブジェクトをスタックに置かないでください。

便利な場所は、物事をきれいにする必要のあるC言語の機能です。

私はこのようなデータの任意のパケットを読み書きできるC関数を持っています。

int do_something() 
{ 
    char buf[9000]; 
    struct ot_packet_t p; 

    pkt_init(&p); 
    pkt_set_type(&p, "WDAT"); 
    pkt_write_uint32(&p, some_var); 
    pkt_write_data(&p, some_data, some_len); 

    // other stuff... 
    // if need to early exit... buf & p cleaned up. An RAII approach. 

    send_packet(buf, pkt_get_length(&p)); 
} 

私はこの質問にC++でタグ付けしただけでなく、C++にも適用できます。 少なくともC++では、一般にauto_ptrを使用してヒープ上に割り当てられた大きなオブジェクトをクリーンアップします。 Cではこれがきちんと正しいとは思わない?

+1

あなたが想像できるすべての言語にタグを付けるだけではありません。この一般的な質問は、固定サイズのスタックを持つプラットフォーム上のネイティブアセンブラにコンパイルされる言語実装に適用されます。 – Puppy

答えて

4

メインストリームPC上のシングルスレッドアプリケーションでは、あまり心配する必要はありません。ここにはいくつかのKiB、そこにはいくつかのKibがあります。最終的には、スタック上のMiBまたは2つに到達する可能性があります。スタックは自動的にアプリケーションのコストを最小限に抑えて拡張されます。

マルチスレッドアプリケーションを扱っていると、状況が変わります。各スレッドには独自のスタックがあり、スレッドの開始時にスタックサイズが固定されていることを理解しています。大きなローカル変数を持つスレッドのスタックを混乱させ始めると、すべてのスタックを消費して領域を使い果たす可能性があります。したがって、より大きなオブジェクトに動的メモリ割り当てを使用して、このような問題に遭遇するのを避けるほうがよいです。シングルスレッドのアプリケーションに対しても動的割り当てを行うことができるので、プログラムがマルチスレッドのプログラムに発展する可能性がある場合は、最初から動的割り当てを使用する必要があります。動的割り当ては、スタック上の自動割り当てよりも遅いことに注意してください。

メモリが制限されているシステムを扱っている場合は、期間が長いオブジェクトを作成しないようにします。あなたは一度に何人が存在するかについて少なくとも心配しなければならず、できるだけ早くそれらがリリースされるようにしなければなりません。

+0

コメントありがとうございます。スレッドを介してライブラリとやりとりするものにリンクされるライブラリにコードを配置します。あなたのコメントは良いです。 – Matt

1

「依存します。マシン上では、デバイス、ブロックのサイズ、スタックの大きさは既にあなたの下にあります。

あなたの例では、非再帰関数の〜9kブロックはかなり良いでしょう。 (ここでは小さな組み込み機器は例外で、同じスタック上で同じことをしていた他の多くの関数がある場合は除きます)

純粋に個人的な経験則として、通常のアプリケーションレベルのコードで数Kを超えるバッファ。あなたの例のようにパケット転送を行っていて、ループしていた場合は、毎回動的な割り当てを行うことによるパフォーマンス上のオーバーヘッドが発生する可能性があるため、スタック上に静的バッファを保持するか、使用するバッファの再利用可能なプールのいくつかの並べ替え。

関連する問題