2008-09-17 32 views
12

Tại sao hạt nhân Linux tạo ra một segfault trên tràn ngăn xếp? Điều này có thể thực hiện gỡ lỗi rất khó xử khi alloca trong c hoặc fortran tạo ra các mảng tràn tạm thời. Chắc chắn nó có thể được điều chỉnh cho thời gian chạy để tạo ra một lỗi hữu ích hơn.Segfault trên ngăn xếp tràn

Trả lời

7

"hạt nhân" (thực ra không phải hạt nhân đang chạy mã của bạn, đó là CPU) không biết mã của bạn tham chiếu đến bộ nhớ mà nó không được phép chạm vào. Nó chỉ biết rằng bạn đã cố gắng để làm điều đó.

Mã:

char *x = alloca(100); 
char y = x[150]; 

có thể không thực sự được đánh giá bởi các CPU như bạn cố gắng truy cập vượt quá giới hạn của x.

Bạn có thể nhấn địa chỉ chính xác cùng với:

char y = *((char*)(0xdeadbeef)); 

BTW, tôi sẽ không khuyến khích việc sử dụng alloca kể từ khi chồng có xu hướng hạn chế hơn nhiều so với đống (sử dụng malloc thay).

+0

Mặc dù stackspace nhanh hơn rất nhiều cho thao tác trên nền cứng. Chỉ cần sử dụng một cách tiết kiệm. Ngoài ra, hãy kiểm tra "Getrlimit" trước khi thực hiện bất kỳ alloca nào. Hãy chắc chắn rằng bạn có đủ không gian còn lại! –

5

Lỗi tràn ngăn xếp là lỗi phân đoạn. Như trong bạn đã phá vỡ giới hạn nhất định của bộ nhớ mà bạn ban đầu được phân bổ. Chồng của kích thước hữu hạn, và bạn đã vượt quá nó. Bạn có thể đọc thêm về nó tại wikipedia

Ngoài ra, một điều tôi đã thực hiện cho các dự án trong quá khứ là viết trình xử lý tín hiệu của riêng mình để phân đoạn (xem tín hiệu trang người đàn ông (2)). Tôi thường bắt được tín hiệu và viết ra "Đã xảy ra lỗi nghiêm trọng" cho bảng điều khiển. Tôi đã làm một số công cụ hơn nữa với cờ checkpoint, và gỡ lỗi.

Để gỡ lỗi segfaults, bạn có thể chạy chương trình trong GDB. Ví dụ, chương trình C sau đây sẽ segfault: # segfault.c #include #include

int main() 
{ 
     printf("Starting\n"); 
     void *foo=malloc(1000); 
     memcpy(foo, 0, 100); //this line will segfault 
     exit(0); 
} 

Nếu tôi biên dịch nó như vậy:

gcc -g -o segfault segfault.c 

và sau đó chạy nó như vậy:

$ gdb ./segfault 
GNU gdb 6.7.1 
Copyright (C) 2007 Free Software Foundation, Inc. 
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> 
This is free software: you are free to change and redistribute it. 
There is NO WARRANTY, to the extent permitted by law. Type "show copying" 
and "show warranty" for details. 
This GDB was configured as "i686-pc-linux-gnu"... 
Using host libthread_db library "/lib/libthread_db.so.1". 
(gdb) run 
Starting program: /tmp/segfault 
Starting 

Program received signal SIGSEGV, Segmentation fault. 
0x4ea43cbc in memcpy() from /lib/libc.so.6 
(gdb) bt 
#0 0x4ea43cbc in memcpy() from /lib/libc.so.6 
#1 0x080484cb in main() at segfault.c:8 
(gdb) 

Tôi tìm hiểu từ GDB rằng có lỗi phân đoạn trên dòng 8. Tất nhiên có nhiều cách xử lý phức tạp hơn ck tràn và các lỗi bộ nhớ khác, nhưng điều này sẽ đủ.

1

Chỉ cần sử dụng Valgrind. Nó sẽ chỉ ra tất cả các lỗi phân bổ bộ nhớ của bạn với độ chính xác tuyệt vời.

42

Bạn thực sự có thể bắt tình trạng tràn ngăn xếp bằng cách sử dụng trình xử lý tín hiệu.

Để làm điều này, bạn phải làm hai việc:

  • Thiết lập một xử lý tín hiệu cho SIGSEGV (segfault) sử dụng sigaction, để làm điều này đặt cờ SO_ONSTACK. Điều này hướng dẫn hạt nhân sử dụng một chồng thay thế khi cung cấp tín hiệu.

  • Gọi sigaltstack() để thiết lập ngăn xếp thay thế mà trình xử lý cho SIGSEGV sẽ sử dụng.

Sau đó, khi bạn tràn ngăn xếp, hạt nhân sẽ chuyển sang ngăn thay thế của bạn trước khi gửi tín hiệu. Khi ở trong bộ xử lý tín hiệu của bạn, bạn có thể kiểm tra địa chỉ gây ra lỗi và xác định xem đó có phải là tràn ngăn xếp hay lỗi thường xuyên.

0

Lỗi tràn ngăn không nhất thiết gây ra sự cố. Nó có thể âm thầm thùng rác dữ liệu của chương trình của bạn nhưng vẫn tiếp tục thực hiện.

Tôi sẽ không sử dụng bộ xử lý SIGSEGV mà thay vào đó khắc phục sự cố ban đầu.

Nếu bạn muốn trợ giúp tự động, bạn có thể sử dụng tùy chọn -Wstack-protector của gcc, điều này sẽ phát hiện một số lỗi tràn vào thời gian chạy và hủy chương trình.

valgrind là tốt cho lỗi phân bổ bộ nhớ động, nhưng không phải cho lỗi ngăn xếp.

0

Một số nhận xét hữu ích, nhưng vấn đề không phải là lỗi phân bổ bộ nhớ. Đó là không có sai lầm trong mã. Nó khá phiền toái trong fortran, nơi thời gian chạy phân bổ các giá trị tạm thời trên stack. Vì vậy, một lệnh như ghi (fp) x, y, z có thể kích hoạt là segfault không có cảnh báo. Sự hỗ trợ kỹ thuật cho trình biên dịch Fortran intel nói rằng không có cách nào mà thư viện thời gian chạy có thể in một thông điệp hữu ích hơn. Tuy nhiên, nếu Miguel là đúng hơn điều này nên có thể như ông đề nghị. Cảm ơn rất nhiều Câu hỏi còn lại sau đó là làm thế nào để trước tiên tôi tìm thấy địa chỉ của lỗi seg và con số ra nếu nó đến từ một tràn ngăn xếp hoặc một số vấn đề khác.

Đối với những người khác tìm thấy sự cố này, có một lá cờ trình biên dịch đặt các chênh lệch tạm thời trên một kích thước nhất định trên heap.

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