2012-01-19 16 views
5

私はstruct {}定義で定義された非常に大きな配列を持つ構造体へのポインタ、サイズが約34MBの浮動小数点型配列を渡して、奇妙な状況に陥っています。奇妙なスタックオーバーフロー?

typedef config_t{ 
    ... 
    float values[64000][64]; 
} CONFIG; 


int32_t Create_Structures(CONFIG **the_config) 
{ 
    CONFIG *local_config; 
    int32_t number_nodes; 

    number_nodes = Find_Nodes(); 

    local_config = (CONFIG *)calloc(number_nodes,sizeof(CONFIG)); 
    *the_config = local_config; 
    return(number_nodes); 
} 


int32_t Read_Config_File(CONFIG *the_config) 
{ 
    /* do init work here */ 
    return(SUCCESS); 
} 


main() 
{ 
    CONFIG *the_config; 
    int32_t number_nodes,rc; 

    number_nodes = Create_Structures(&the_config); 

    rc = Read_Config_File(the_config); 
    ... 
    exit(0); 
} 

コードは罰金コンパイルが、私はそれを実行しようとすると、私は{Read_Config_Fileの下に()​​でSIGSEGVを取得します:一言で言えば、擬似コードは次のようになります。

(gdb) run 
... 
Program received signal SIGSEGV, Segmentation fault. 
0x0000000000407d0a in Read_Config_File (the_config=Cannot access memory at address 0x7ffffdf45428 
) at ../src/config_parsing.c:763 
763 { 
(gdb) bt 
#0 0x0000000000407d0a in Read_Config_File (the_config=Cannot access memory at address 0x7ffffdf45428 
) at ../src/config_parsing.c:763 
#1 0x00000000004068d2 in main (argc=1, argv=0x7fffffffe448) at ../src/main.c:148 

私は小さなアレイでこのようなことをしてきました。そして、不思議なことに、0x7fffffffe448 - 0x7ffffdf45428 = 0x20B8EF8、または約34MBのフロート配列。

Valgrindのは私に似て出力与える:

==10894== Warning: client switching stacks? SP change: 0x7ff000290 --> 0x7fcf47398 
==10894==   to suppress, use: --max-stackframe=34311928 or greater 
==10894== Invalid write of size 8 
==10894== at 0x407D0A: Read_Config_File (config_parsing.c:763) 
==10894== by 0x4068D1: main (main.c:148) 
==10894== Address 0x7fcf47398 is on thread 1's stack 

エラー・スタック・ポインタをつかう私へのメッセージのすべてのポイントが、a)を、私は、関数のエントリとにクラッシュ1全体を実行したことがないB)実際の配列ではなく、ポインタを渡しています。

誰かがこれで私を助けることができますか?私はカーネル2.6.18とgcc 4.1.2を実行している64ビットCentOSボックスにいます。

ありがとう!

マット

+9

擬似コードを投稿すると、疑似回答のみが表示されます。悪魔は細部にあり、おそらくすべてが重要です。 –

+2

'Read_Config_File'のソースを確認できますか?それはあなたが逃したブロックの中に問題があるように見えます。 – Borealid

+0

calloc()の戻り値をテストしていないため、失敗する可能性があります。 –

答えて

1

あなたは、これらの巨大なconfig_t構造体の1つを割り当ててスタックを爆破しました。 gdbの出力にある証拠に関する2つのスタックポインタ0x7fffffffe448と0x7ffffdf45428は、これを非常に示唆しています。

$ gdb 
GNU gdb 6.3.50-20050815 ...blahblahblah... 
(gdb) p 0x7fffffffe448 - 0x7ffffdf45428 
$1 = 34312224 

config_t構造体のサイズに一致する〜34MBの定数があります。システムはそれほど多くのスタックスペースをデフォルトでは提供しないので、オブジェクトをスタックから移動するかスタックスペースを増やすかのどちらかです。

+0

機能がどれくらい積み重なるかを教えてくれる "糸くず"のようなツールはありますか?後見では、故障の原因はかなり分かりましたが、そのような問題が存在するかどうかを知りたいと思っています。 – tranzmatt

+0

gccは実行時のチェックのために-fstack-limit- *を持っていますが、コンパイル時に過度に大きなスタック割り当てについて警告するものは何もありません。 –

1

短い答えは、スタックの上に置くことになる、どこかのローカル変数として宣言config_tがなければならないということです。おそらくタイプミス:CONFIG宣言の後のどこかに*がありません。

+0

それが問題でした。私は配列内のジャムする前に関数内のconfig_t構造体の一時的なコピーを保持していたことを忘れてしまいました。私は配列を他の場所に移動しましたが、今はそれが失敗しません。ありがとう。 – tranzmatt