2012-01-19 43 views
5

Tôi đang chạy vào một tình huống lạ với việc truyền một con trỏ tới một cấu trúc với một mảng rất lớn được định nghĩa trong định nghĩa struct {}, một mảng float có kích thước khoảng 34MB. Tóm lại, các psuedo-mã trông như thế này:Ngăn xếp ngăn xếp lạ?

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); 
} 

mã biên dịch tốt, nhưng khi tôi cố gắng chạy nó, tôi sẽ nhận được một SIGSEGV tại {dưới Read_Config_File().

(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 

Tôi đã làm điều này mọi lúc, với các mảng nhỏ hơn. Và kỳ lạ là 0x7fffffffe448 - 0x7ffffdf45428 = 0x20B8EF8 hoặc khoảng 34MB mảng nổi của tôi.

Valgrind sẽ cho tôi ra tương tự:

==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 

Các thông báo lỗi tất cả các điểm đến tôi clobbering con trỏ ngăn xếp, nhưng a) Tôi chưa bao giờ chạy ngang qua một mà treo trên lối vào của hàm và b) Tôi đi qua con trỏ xung quanh, không phải mảng thực sự.

Ai đó có thể giúp tôi với điều này không? Tôi đang ở trên hộp CentOS 64 bit chạy hạt nhân 2.6.18 và gcc 4.1.2

Cảm ơn!

Matt

+9

Đăng mã giả sẽ chỉ giúp bạn nhận được câu trả lời giả. Ma quỷ ở trong các chi tiết, và có lẽ chúng sẽ là vấn đề. –

+2

Chúng ta có thể thấy nguồn của 'Read_Config_File' không? Đó là nơi mà vấn đề có vẻ là, trong khối bạn elided. – Borealid

+0

Bạn không kiểm tra giá trị trả về của calloc(), có thể không thành công. –

Trả lời

1

Bạn đã thổi lên ngăn xếp bằng cách phân bổ một trong các cấu hình config_t khổng lồ này lên đó. Hai con trỏ ngăn xếp trên các bằng chứng trong đầu ra gdb, 0x7fffffffe448 và 0x7ffffdf45428, rất gợi ý về điều này.

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

Hằng số ~ 34MB của bạn khớp với kích thước của cấu hình config_t. Hệ thống không cung cấp cho bạn nhiều không gian ngăn xếp theo mặc định, do đó, hoặc di chuyển đối tượng ra khỏi ngăn xếp hoặc tăng không gian ngăn xếp của bạn.

+0

Có công cụ "lint" giống như có thể cho tôi biết số lượng một hàm sẽ tăng lên không? Trong tầm nhìn xa, bây giờ nó là khá rõ ràng những gì các sự cố được, nhưng tôi rất muốn biết lên phía trước nếu vấn đề như vậy tồn tại. – tranzmatt

+0

gcc có giới hạn -fstack- * để kiểm tra thời gian chạy, nhưng tôi biết không có gì cảnh báo về phân bổ quá lớn ngăn xếp tại thời gian biên dịch. –

1

Câu trả lời ngắn gọn là phải có một config_t tuyên bố như là một biến địa phương nơi nào đó, mà sẽ đặt nó trên stack. Có thể là lỗi chính tả: thiếu * sau khi khai báo CONFIG ở đâu đó.

+0

Đó là vấn đề. Tôi đã quên tôi đã giữ một bản sao tạm thời của cấu trúc config_t trong hàm trước khi gây nhiễu mảng bên trong. Tôi di chuyển các mảng ở nơi khác và bây giờ nó không seg lỗi. Cảm ơn. – tranzmatt

Các vấn đề liên quan