どのようにしてスタック変数がC ++の静的配列をGCCで上書きしないようにすることができますか?

私はスタック上で自動変数として宣言されている配列が静的に宣言されている配列を上書きするという問題があります。サイズと知的財産の両方の理由から正確なコードを引用することはできませんが、その概要は次のとおりです。

私は次の構造体を持っています:

struct mystruct_type {
    const int list_size;
    const int* list;
};

私はこれらの構造体のグローバルな静的配列を持っています:

struct mystruct_type mystruct_ar[] = {
    {3, (int[]){1, 2, 3}},
    {2, (int[]){1, 3}},
    {5, (int[]){4, 2, 3, 4, 5}}
};

この配列はライブラリにコンパイルされたソースファイルにあります。

私は、自動配列を持つ別のライブラリにコンパイルされた別のソースファイルを持っています:

void my_func(void) 
{
    char my_string[1000];

   //etc...
}

これがすべてリンクされていると、 mystruct_ar にある list one code>にコピーし、 my_string に何かをコピーすると、その list の要素がオーバーライドされ、さまざまな問題が発生します。

コンパイラとリンカの仕組みを理解すると、スタック( my_string が宣言されている)は独立した非配列になっていますが、静的配列とそのすべてのサブアレイは、オーバーラップ領域。この重複を引き起こす原因は何ですか?私は何を確認できますか?

私はSuSE10 Linux(x86-64_linux26)でGCC 4.3.2を使用しています。すべてが静的にリンクされています。

EDIT: a few comments below said that this doesn't compile. They are right. In the process of sanitizing my snippet for presentation I neglected to cast the list array to int[]. This is fixed above.

0
@hmjd:これを修正しました。
追加された 著者 Nathan Fellman,
これはコンパイルされません。 int * を多くの int に初期化しようとしています。テストでは、問題がなくなるかどうかを判断するために、 const int * const int [10] に変更することをお勧めします。
追加された 著者 hmjd,
コードを実行するとvalgrindが苦情を出しますか?
追加された 著者 BatchyX,

3 答え

私はこのコードがコンパイルされるとは思わない。具体的には、リストポインタのmystruct_arに{list、of、ints}を渡すことはできません。上記のintの各配列を別々に宣言しなければなりません。

実際にエラーを示すか、実際のコードスニペットで失敗した一貫したサンプルを提示する必要があります。

1
追加された
私はスニペットでこれを修正しました。
追加された 著者 Nathan Fellman,

この重複の原因は何ですか?

あなたは、複数のスレッドを使用しているかどうかは言いませんでした。もしあなたがそうであれば、 my_string は(制限された)スタックをオーバーフローし、意図しないグローバルデータと重なる可能性が非常に高いです。

Linuxの典型的なスタックは8MBで、デフォルトのガード領域は1ページ(= 4K)です。これにより、実際にスタックがオーバーフローしている(8MBがかなり大きい)ことはありませんし、1000要素の my_string はガード領域に触れることなくガード領域を "ステップオーバー"できます(ガード領域に触れると<コード> SIGSEGV )。

しかし、関連するすべての詳細を教えてくれない可能性があります。デフォルト以外の属性を持つスレッドを作成する場合は、小さなスタックで作成し、ガード領域を無効にしますか?

さらに悪いことに、( pthread_attr_setstackaddr で)固定スタック領域を持つスレッドを作成している可能性があり、その固定スタック領域はグローバル配列である可能性があります。あなた(またはあなたが呼んでいるサードパーティのコード)がそのを行う場合、グローバルを他のグローバル(スタックとして使用されている)から分離するものはなく、衝突ガード領域の)は完全に可能性があります。

例えば、コルーチンスタイルのプログラミング(本質的にユーザレベルのスレッド)を使用すると、スレッドなしでオーバーフローが可能です。 makecontext / swapcontext などのメカニズムを使用してください。

0
追加された
これは、シングルスレッドアプリケーションであることを除いて、興味深い考えです。
追加された 著者 Nathan Fellman,

スタックのサイズはコンパイル時ではなく実行時に決定されます。 ulimit -s を実行して現在の最大スタックサイズを調べ、( ulimit -s 16384 のような)引数を渡して値を大きくします。私のLinuxマシンはどちらも、現在のスタックサイズとして8192を示しています。それを増やして、あなたのアプリがうまくいくかどうかを確認してください。

0
追加された
@StilesCrisis "スタック制限を吹き飛ばすとクラッシュする"それは特定の特定の条件の下でのみ真であり、そうでなければ偽です。
追加された 著者 Employed Russian,
スタック制限をブローすると、メモリストームではなくクラッシュが発生します。
追加された 著者 StilesCrisis,