Ý nghĩa của mã ngoại lệ “EXC_I386_GPFLT” là gì?


117

Ý nghĩa của mã ngoại lệ là EXC_I386_GPFLTgì?

Ý nghĩa của nó có thay đổi tùy theo tình huống không?

Trong trường hợp đó, tôi đang đề cập đến loại EXC_BAD_ACCESSngoại lệ với mã ngoại lệEXC_I386_GPFLT

Chương trình được phát triển trên Xcode 5.0.1, xử lý cblas_zgemm()thư viện BLAS. (Chà, tôi đoán nó không thành vấn đề ...)

Cảm ơn rât nhiều!

Câu trả lời:


112

EXC_I386_GPFLT chắc chắn đang đề cập đến "Lỗi bảo vệ chung", đó là cách x86 cho bạn biết rằng "bạn đã làm điều gì đó mà bạn không được phép làm". Thông thường KHÔNG có nghĩa là bạn truy cập ngoài giới hạn bộ nhớ, nhưng có thể là mã của bạn đang vượt quá giới hạn và khiến mã / dữ liệu xấu được sử dụng theo cách gây ra vi phạm bảo vệ ở một số loại.

Thật không may, thật khó để tìm ra chính xác vấn đề là gì nếu không có thêm ngữ cảnh, có 27 nguyên nhân khác nhau được liệt kê trong Sách hướng dẫn lập trình viên AMD64 của tôi, Tập 2 từ năm 2005 - theo tất cả các tài khoản, có lẽ 8 năm sau sẽ có thêm một vài nguyên nhân hơn.

Nếu đó là hệ thống 64 bit, một tình huống hợp lý là mã của bạn đang sử dụng "con trỏ không chuẩn" - nghĩa là địa chỉ 64 bit được tạo theo cách mà 16 bit phía trên của địa chỉ không tất cả các bản sao trên cùng của 48 bit thấp hơn (nói cách khác, 16 bit trên cùng của một địa chỉ tất cả phải là 0 hoặc tất cả là 1, dựa trên bit ngay dưới 16 bit). Quy tắc này được đặt ra để đảm bảo rằng kiến ​​trúc có thể "mở rộng một cách an toàn số lượng bit hợp lệ trong dải địa chỉ". Điều này sẽ chỉ ra rằng mã đang ghi đè một số dữ liệu con trỏ bằng những thứ khác hoặc đi ra ngoài giới hạn khi đọc một số giá trị con trỏ.

Một nguyên nhân có khả năng khác là truy cập không được căn chỉnh với thanh ghi SSE - nói cách khác, đọc một thanh ghi SSE 16 byte từ một địa chỉ không được căn chỉnh 16 byte.

Như tôi đã nói, có nhiều lý do có thể khác, nhưng hầu hết những lý do đó liên quan đến những thứ mà mã "bình thường" sẽ không thực hiện được trong hệ điều hành 32 hoặc 64-bit (chẳng hạn như tải các thanh ghi phân đoạn có chỉ mục bộ chọn không hợp lệ hoặc ghi vào MSR's (thanh ghi mô hình cụ thể)).


24

Để gỡ lỗi và tìm nguồn: Kích hoạt Zombies cho ứng dụng (Sản phẩm \ Scheme) và Khởi chạy Dụng cụ, Chọn Zombies. Chạy ứng dụng của bạn trong Xcode Sau đó chuyển đến Instruments bắt đầu ghi. Quay lại Ứng dụng của bạn và thử tạo lỗi. Các công cụ sẽ phát hiện ra cuộc gọi xấu (tới zombie) nếu có.

Hy vọng nó giúp!



23

Bạn thường có thể lấy thông tin từ các tệp tiêu đề. Ví dụ:

$ cd /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk
$ find usr -name \*.h -exec fgrep -l EXC_I386_GPFLT {} \;
usr/include/mach/i386/exception.h
^C
$ more usr/include/mach/i386/exception.h
....
#define EXC_I386_GPFLT          13      /* general protection fault     */

OK, vì vậy đó là một lỗi bảo vệ chung (dù sao cũng như tên gọi của nó). Googling "Lỗi bảo vệ chung i386" mang lại nhiều lần truy cập, nhưng điều này có vẻ thú vị:

Bảo vệ bộ nhớ cũng được thực hiện bằng cách sử dụng các bộ mô tả phân đoạn. Đầu tiên, bộ xử lý kiểm tra xem giá trị được tải trong thanh ghi phân đoạn có tham chiếu đến bộ mô tả hợp lệ hay không. Sau đó, nó kiểm tra xem mọi địa chỉ tuyến tính được tính toán có thực sự nằm trong phân đoạn hay không. Ngoài ra, kiểu truy cập (đọc, ghi hoặc thực thi) được kiểm tra dựa trên thông tin trong bộ mô tả phân đoạn. Bất cứ khi nào một trong những lần kiểm tra này không thành công, ngoại lệ (ngắt) 13 (hex 0D) sẽ được nâng lên. Ngoại lệ này được gọi là Lỗi bảo vệ chung (GPF).

Điều đó 13khớp với những gì chúng ta đã thấy trong các tệp tiêu đề, vì vậy nó trông giống như vậy. Tuy nhiên, theo quan điểm của lập trình viên ứng dụng, điều đó chỉ có nghĩa là chúng ta đang tham khảo bộ nhớ mà chúng ta không nên có, và nó không thực sự quan trọng bằng cách nào nó được triển khai trên phần cứng.


1
Tuy nhiên, hệ điều hành hiện đại không sử dụng phân đoạn để bảo vệ bộ nhớ nói chung. Tất cả đều được thực hiện với MMU, và sẽ dẫn đến PF, vector 14 (thường được hiển thị là "Lỗi phân đoạn").
Mats Petersson

16

Tôi tự hỏi tại sao điều này xuất hiện trong các bài kiểm tra đơn vị của tôi.

Tôi đã thêm một khai báo phương thức vào một giao thức bao gồm throws; nhưng phương pháp ném tiềm năng thậm chí không được sử dụng trong thử nghiệm cụ thể đó. Kích hoạt Zombies trong thử nghiệm nghe có vẻ quá rắc rối.

Hóa ra ⌘K clean đã lừa được. Tôi luôn bối rối khi điều đó giải quyết được các vấn đề thực tế.


Điều này cũng đã sửa nó cho tôi trong Swift. Cảm ơn!
lwdthe1

8

Tôi đã có một ngoại lệ tương tự ở Swift 4.2. Tôi đã dành khoảng nửa giờ để cố gắng tìm lỗi trong mã của mình, nhưng sự cố đã xảy ra sau khi đóng Xcode và xóa thư mục dữ liệu dẫn xuất. Đây là phím tắt:

rm -rf ~/Library/Developer/Xcode/DerivedData

2

Trong trường hợp của tôi, lỗi đã xảy ra trong Xcode khi chạy ứng dụng trên trình mô phỏng iOS. Trong khi tôi không thể trả lời câu hỏi cụ thể "lỗi nghĩa là gì", tôi có thể nói điều gì đã giúp tôi, có thể nó cũng giúp ích cho người khác.

Giải pháp cho tôi là Erase All Content and Settingstrong trình mô phỏng và Clean Build Folder...trong Xcode.


1

Tôi đã gặp sự cố này khi rời khỏi chế độ xem (bật trở lại chế độ xem trước đó).

lý do là có

addSubview(view)
view.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
    view.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor),
    view.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor),
    view.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor),
    view.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor)
])

Thay đổi safeAreaLayoutGuideđể selfgiải quyết vấn đề.

Có nghĩa là căn chỉnh chế độ xem với đầu, cuối, trên, dưới của chế độ xem thay vì đến khu vực an toàn)


0

Điều này xảy ra với tôi vì Xcode dường như không thích tôi sử dụng cùng một tên biến trong hai lớp khác nhau (tuân theo cùng một giao thức, nếu điều đó quan trọng, mặc dù tên biến không có liên quan gì trong bất kỳ giao thức nào). Tôi chỉ đơn giản là đổi tên biến mới của mình.

Tôi đã phải bước vào bộ cài đặt nơi nó bị lỗi để xem nó, trong khi gỡ lỗi. Câu trả lời này áp dụng cho iOS


0

Nếu lỗi được đưa ra bên trong một bao đóng được xác định selfunowned, bạn có thể bị giới hạn những gì bạn có thể truy cập và sẽ nhận được mã lỗi này trong một số tình huống nhất định. Đặc biệt là trong khi gỡ lỗi. Nếu đây là trường hợp của bạn, hãy thử thay đổi [unowned self]thành[weak self]


0

Tôi gặp lỗi này khi thực hiện việc này:

 NSMutableDictionary *aDictionary=[[NSMutableDictionary alloc] initWithObjectsAndKeys:<#(nonnull id), ...#>, nil]; //with 17 objects and keys

Nó biến mất khi tôi hoàn nguyên về:

NSMutableDictionary *aDictionary=[[NSMutableDictionary alloc] init];
[aDictionary setObject:object1 forKey:@"Key1"]; //17 times

0

Đối với tôi, vấn đề liên quan đến bảng phân cảnh, có tùy chọn bản dựng ViewController cho thiết lập iOS 9.0 trở lên trước đó được đặt cho iOS 10.0 trở lên. Trên thực tế, tôi muốn hạ cấp phiên bản từ 10 xuống iOS 9.3.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.