2012-01-19 93 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 

錯誤信息都指向我重挫堆棧指針,但)我從來沒有穿過一個在函數的入口和崩潰運行B)我傳遞指針,而不是實際的數組。

有人可以幫我解決這個問題嗎?我在一個運行內核2.6.18和gcc 4.1.2的64位CentOS盒子上。

謝謝!

馬特

+9

發佈僞代碼只會讓你僞造答案。魔鬼在細節中,他們可能都很重要。 –

+2

我們可否看到'Read_Config_File'的來源?這就是問題出現的地方,在你消失的地方。 – Borealid

+0

您不測試可能失敗的calloc()的返回值。 –

回答

1

你已經通過將這些巨大的config_t結構體中的一個分配到它上面而炸燬了堆棧。 gdb輸出中有證據的兩個堆棧指針0x7fffffffe448和0x7ffffdf45428對此非常有幫助。

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

您的〜34MB常量與config_t結構的大小相匹配。系統默認情況下不會爲您提供太多的堆棧空間,因此無論是將對象移出堆棧還是增加堆棧空間。

+0

有沒有一種類似「lint」的工具可以告訴我一個函數會吞噬多少堆棧?事後看來,現在很明顯的是故障是什麼,但如果存在這樣的問題,我很樂意知道。 – tranzmatt

+0

對於運行時檢查,gcc具有-fstack-limit- *,但我知道沒有任何警告編譯時的堆棧分配過大。 –

1

簡短的回答是,必須有聲明爲一個局部變量某處config_t,它會把它的堆棧。可能是一個錯字:CONFIG聲明之後丟失*

+0

這是問題所在。我忘記了在干擾數組之前,我在函數中保留了一個臨時的config_t結構副本。我在其他地方移動了陣列,現在它不會發生故障。謝謝。 – tranzmatt