2011-01-25 80 views
7

có cách nào để xử lý các trường hợp ngoại lệ của CPU như lỗi phân đoạn hoặc chia cho 0 không? Cho phép nói, tôi cần phải gọi một số chức năng không an toàn tiềm năng (ví dụ từ một tệp trình cắm thêm), điều đó có thể gây ra sự phân đoạn hoặc một số vấn đề khác mà tôi không thể kiểm tra trước khi thực thi nó. Tôi biết, thư viện chuẩn C có các chức năng xử lý tín hiệu, nhưng tôi không biết cách sử dụng chúng để xử lý vấn đề để tránh chấm dứt chương trình (tôi đoán, tôi không thể nhảy đến vị trí trước khi thực thi các hàm có vấn đề , hay tôi có thể?). Dưới cửa sổ, tôi có thể sử dụng trình xử lý ngoại lệ SEH, nhưng tôi không thể thực hiện điều đó trong Linux hoặc bất kỳ hệ điều hành nào khác. Điều gì về việc sử dụng trình xử lý ngoại lệ của riêng tôi để xử lý các vấn đề này, mức độ khác nhau giữa Windows/Linux là bao nhiêu? Điều đó có thể được thậm chí có thể (thông qua lắp ráp - cho phép nói chỉ trên nền tảng x86)?Xử lý ngoại lệ CPU trong C++

Tôi đang yêu cầu phần lớn sự tò mò, tôi không cố gắng giải quyết vấn đề hiện tại (chưa). Cảm ơn

+0

Điều này có thể quan tâm: http://stackoverflow.com/questions/4747934/c-catch-a-divide-by-zero-error –

+1

trong khi trong trường hợp của một segfault bạn không thể thực sự làm bất cứ điều gì, tôi phải thừa nhận sự phân chia bằng không, trường hợp tràn và tràn luôn luôn đánh tôi như là tỷ lệ cược và nó sẽ là tuyệt vời để có thể bắt chúng. –

Trả lời

5

libsigsegv là thư viện đa nền tảng để xử lý lỗi phân đoạn và tràn ngăn xếp. Tuy nhiên, trong phần lớn các trường hợp, khi bạn phát hiện lỗi phân đoạn, điều đúng đắn cần làm là chấm dứt thực hiện nhanh nhất có thể thay vì cố gắng khôi phục từ nó. Một segfault thường là dấu hiệu của một lỗi hoặc bộ nhớ bị hỏng, và một khi bạn đã bị hỏng bộ nhớ, nó hầu như không thể phục hồi từ đó.

+0

Có, giải pháp như vậy sẽ chỉ áp dụng cho một vài trường hợp, nơi tôi có thể đảm bảo môi trường của chương trình không bị hỏng. –

+0

@ John Holecek Bạn có thể đảm bảo như thế nào trong mọi trường hợp? –

+0

Ví dụ để kiểm tra nếu giá trị con trỏ trỏ đến một vị trí bộ nhớ hợp lệ - một thứ như vậy có thể hữu ích cho một bộ thu gom rác của một số loại. –

2

Vấn đề là nếu plugin seg bị lỗi, bạn không thể đảm bảo trạng thái chương trình chính của bạn sẽ ở nữa. Ngay cả khi bạn có thể bắt SIGSEGV (mà tôi tin rằng bạn có thể) bạn sẽ không có một cách tốt để phục hồi trong ứng dụng của bạn.

Những gì bạn phải làm là chạy plugin trong quy trình chỉnh sửa fork để nếu chương trình chính của bạn bị hỏng cũng không bị gỡ xuống. Bạn có thể giao tiếp giữa các quá trình với một đường ống ví dụ.

+0

Ví dụ với plugin chỉ là một ý tưởng mà nó có thể được sử dụng. Plugin như vậy sẽ phải chạy như một tiến trình con, như bạn đã đề xuất hoặc nó sẽ phải tuân thủ một quy tắc nghiêm ngặt, như những gì nó có thể, hoặc có thể không làm (nhưng một lần nữa, tôi sẽ không thể thực thi điều này). Tuy nhiên trong trường hợp tôi chỉ cần đọc/ghi vào một số bộ nhớ, tôi sẽ có thể phục hồi trong trường hợp segfault. –

+0

Có, đó sẽ là một điều phức tạp để làm –

1

Không, không có cách nào tiêu chuẩn. Trong C++, chẳng hạn như "ngoại lệ CPU" là biểu hiện của Hành vi không xác định, tức là tiêu chuẩn C++ không chỉ định bất kỳ điều gì về hành vi của chúng hoặc bất kỳ điều gì xảy ra sau đó. Ngay cả khái niệm "segfault" không tồn tại trong C++ chuẩn. Dereferencing một con trỏ NULL có thể thiết lập máy tính của bạn trên lửa, và rõ ràng là có rất ít trái để bắt tại điểm đó.

C cũng không giải quyết vấn đề này: SIGSEGV không phải là tín hiệu C chuẩn; nó là một phần mở rộng POSIX. Ví dụ, Windows không có SIGSEGV.

2

Điều này không được bao gồm trong tiêu chuẩn C++, tuy nhiên hệ điều hành máy tính để bàn phổ biến cung cấp các tiện ích để thực hiện việc này. Windows có xử lý ngoại lệ có cấu trúc (SEH) cho các phần mở rộng trình biên dịch có liên quan, và POSIX cung cấp xử lý tín hiệu.

Thông thường, tôi sẽ nói rằng bạn không nên bắt ngoại lệ CPU - chúng chỉ xảy ra nếu chương trình của bạn bị lỗi và tại thời điểm đó, đã đến lúc phải tháo gỡ trình gỡ lỗi, không tiếp tục.

Bạn không thể sử dụng cùng một phương pháp tiếp cận ngay cả trong bộ lắp ráp. Các cơ sở này được cung cấp bởi hệ điều hành OS- khi CPU đặt ra một ngoại lệ, nó đi tới hệ điều hành để quyết định phải làm gì với nó, chứ không phải chế độ người dùng. Không chỉ vậy, nhưng tôi sẽ nói rằng SEH và xử lý tín hiệu có thể dễ dàng đủ khác nhau để đảm bảo phương pháp tiếp cận cơ bản khác nhau khi sử dụng chúng trong mã, do đó, một đơn giản #ifdef sẽ không cắt nó.

setjmplongjmp chỉ có thể hoạt động cho "tín hiệu" được tạo bởi mã chế độ người dùng chứ không phải ở cấp hệ điều hành.

0

xử lý tín hiệu có thể sửa chữa lên chương trình thực hiện để một lúc nào đó; những gì chính xác được cho phép được ghi lại trong trang hướng dẫn sử dụng tín hiệu (7).

Có triển khai sẽ

  • trở lại giảng dạy đứt gãy từ xử lý SIGSEGV (điều này cho phép bạn thay đổi bản đồ bộ nhớ và quay trở lại), và

  • đi đến hướng dẫn sau lỗi cho SIGFPE (do đó trình xử lý tín hiệu của bạn cần tìm kiếm hướng dẫn và cung cấp kết quả)

Lưu ý rằng đây là thực hiện- được xác định ở mức tốt nhất. Sổ tay hướng dẫn bạn không nên dựa vào bất kỳ điều nào trong số này. Bạn đa được cảnh bao. :)