2010-05-20 62 views
81

Làm cách nào để chúng tôi xác định nơi có lỗi trong mã của chúng tôi gây ra segmentation fault?Xác định dòng mã gây ra lỗi phân đoạn?

Sau khi viết một số mã, để xác định nơi tôi có lỗi phân đoạn, trình biên dịch của tôi (gcc) có cho tôi biết Vị trí của lỗi trong chương trình của tôi không?

+2

Không thể gcc/gdb. Bạn có thể tìm ra _where_ segfault xảy ra, nhưng lỗi thực tế có thể ở một vị trí hoàn toàn khác. –

Trả lời

121

GCC không thể làm điều đó nhưng GDB chắc chắn có thể. Biên dịch bạn chương trình sử dụng -g chuyển đổi, như thế này:

gcc program.c -g 

Sau đó sử dụng gdb:

$ gdb ./a.out 
(gdb) run 
<segfault happens here> 
(gdb) backtrace 
<offending code is shown here> 

Here là một hướng dẫn tốt đẹp để giúp bạn bắt đầu với GDB.

+9

Sử dụng backbace của gdb ('bt') sẽ tìm thấy nơi nó xảy ra nhanh chóng. – nategoose

+1

@nategoose: True :) – nc3b

+12

Lưu ý rằng nơi segfault xảy ra thường chỉ là một đầu mối là nơi "sai lầm gây ra" nó là trong mã.Một đầu mối quan trọng, nhưng nó không nhất thiết là nơi mà vấn đề cư trú. – mpez0

13

Bạn cũng có thể sử dụng kết xuất lõi và sau đó kiểm tra nó bằng gdb. Để có được thông tin hữu ích, bạn cũng cần biên dịch với cờ -g.

Bất cứ khi nào bạn nhận được thông báo:

Segmentation fault (core dumped) 

một tập tin lõi được viết vào thư mục hiện tại của bạn. Và bạn có thể kiểm tra nó bằng lệnh

gdb your_program core_file 

Tệp chứa trạng thái của bộ nhớ khi chương trình bị lỗi. Một kết xuất lõi có thể hữu ích trong quá trình triển khai phần mềm của bạn.

Đảm bảo hệ thống của bạn không đặt kích thước tệp kết xuất lõi thành 0. Bạn có thể thiết lập nó để không giới hạn với:

ulimit -c unlimited

cẩn thận mặc dù! rằng các bãi lõi có thể trở nên rất lớn.

+0

Tôi đã chuyển sang Arch-Linux gần đây. Thư mục hiện tại của tôi không chứa tệp kết xuất lõi. Làm thế nào tôi có thể tạo ra nó? – Abhinav

+0

Bạn không tạo; Linux. Cốt lõi được lưu trữ tại các vị trí khác nhau trên các lớp phủ khác nhau - Google xung quanh. Đối với Arch Linux, hãy đọc https://wiki.archlinux.org/index.php/Core_dump – Mawg

2

Câu trả lời của Lucas về các bãi lõi là tốt. Trong .cshrc của tôi, tôi có:

alias core 'ls -lt core; echo where | gdb -core=core -silent; echo "\n"' 

để hiển thị backtrace bằng cách nhập 'lõi'. Và đóng dấu ngày, để đảm bảo tôi nhìn vào các tập tin ngay :(

Added:.. Nếu có một chồng tham nhũng lỗi, sau đó các vết lùi áp dụng cho các bãi chứa lõi thường là rác Trong trường hợp này , chạy chương trình trong phạm vi gdb có thể cho kết quả tốt hơn, theo câu trả lời được chấp nhận (giả sử lỗi có thể dễ dàng tái tạo) và cũng cần cẩn thận với nhiều quá trình bán phá giá lõi cùng một lúc, một số hệ điều hành thêm PID vào tên của tệp lõi.

+4

này và đừng quên 'ulimit -c unlimited' để bật các vùng lõi ở vị trí đầu tiên. –

+0

@James: Đúng. Lucas đã đề cập đến điều này. Và đối với những người trong chúng ta vẫn còn mắc kẹt trong csh, hãy sử dụng 'giới hạn'. Và tôi đã không bao giờ có thể đọc stackdumps CYGWIN (nhưng tôi đã không cố gắng cho 2 hoặc 3 năm). –

24

Ngoài ra, bạn có thể cung cấp cho Valgrind một thử: nếu bạn cài đặt Valgrind và chạy valgrind --leak-check = full, sau đó nó sẽ chạy chương trình của bạn và hiển thị stack t cuộc đua cho bất kỳ segfaults, cũng như bất kỳ bộ nhớ không hợp lệ đọc hoặc viết và rò rỉ bộ nhớ. Nó thực sự khá hữu ích.

+2

+1, Valgrind nhanh hơn/dễ sử dụng hơn nhiều để phát hiện lỗi bộ nhớ. Trên các bản dựng không được tối ưu hóa với các biểu tượng gỡ lỗi, nó sẽ cho bạn biết _exactly_ nơi xảy ra sự cố segfault và tại sao. –

+0

Đáng buồn là sự biến mất của tôi biến mất khi biên dịch với -g -O0 và kết hợp với valgrind. – JohnMudd

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