Что означает код исключения «EXC_I386_GPFLT»?

117

Что означает код исключения EXC_I386_GPFLT?

Его значение меняется в зависимости от ситуации?

В этом случае я имею в виду тип EXC_BAD_ACCESSисключения с кодом исключения.EXC_I386_GPFLT

Программа разработана на Xcode 5.0.1 и имеет дело с cblas_zgemm()библиотекой BLAS (ну, думаю, это не имеет значения ...)

Большое спасибо!

Lewen
источник

Ответы:

112

EXC_I386_GPFLT, безусловно, имеет в виду «общую ошибку защиты», которая является способом x86 сказать вам, что «вы сделали то, что вам не разрешено». Обычно это НЕ означает, что вы обращаетесь за пределами памяти, но может случиться так, что ваш код выходит за границы и приводит к использованию плохого кода / данных таким образом, который приводит к некоторому нарушению защиты.

К сожалению, может быть трудно точно определить, в чем проблема, без дополнительного контекста, в моем Руководстве программиста AMD64, том 2 от 2005 года, перечислено 27 различных причин - по всем оценкам, вероятно, что 8 лет спустя добавилось бы несколько Больше.

Если это 64-битная система, вероятным сценарием является то, что ваш код использует «неканонический указатель» - это означает, что 64-битный адрес сформирован таким образом, что старшие 16 бит адреса не все копии верхних 48 нижних битов (другими словами, все верхние 16 бит адреса должны быть 0 или все 1, в зависимости от бита чуть ниже 16 бит). Это правило применяется, чтобы гарантировать, что архитектура может «безопасно увеличить количество действительных битов в диапазоне адресов». Это будет означать, что код либо перезаписывает некоторые данные указателя другим материалом, либо выходит за пределы при чтении некоторого значения указателя.

Другой вероятной причиной является невыровненный доступ к регистру SSE - другими словами, чтение 16-байтового регистра SSE с адреса, который не выровнен по 16 байтам.

Как я уже сказал, существует множество других возможных причин, но большинство из них связаны с вещами, которые «нормальный» код не мог бы делать в 32- или 64-разрядной ОС (например, загрузка регистров сегмента с недопустимым индексом селектора или запись в MSR (регистры конкретной модели)).

Матс Петерссон
источник
24

Чтобы отладить и найти источник: Включите Зомби для приложения (Продукт \ Схема) и Запустите Инструменты, выберите Зомби. Запустите приложение в Xcode. Затем перейдите в Инструменты, чтобы начать запись. Вернитесь в свое приложение и попробуйте сгенерировать ошибку. Приборы должны обнаруживать плохой вызов (зомби), если он есть.

Надеюсь, поможет!

Халид Мамедов
источник
How-to-enable-nszombie-in-xcode
Саймон Эпскэмп,
23

Часто информацию можно получить из файлов заголовков. Например:

$ 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     */

Хорошо, так что это общая неисправность защиты (как следует из названия). Поиск в Google "общая ошибка защиты i386" дает много совпадений, но это выглядит интересно:

Защита памяти также реализуется с помощью дескрипторов сегментов. Сначала процессор проверяет, ссылается ли значение, загруженное в регистр сегмента, на действительный дескриптор. Затем он проверяет, действительно ли каждый вычисленный линейный адрес находится внутри сегмента. Кроме того, тип доступа (чтение, запись или выполнение) сверяется с информацией в дескрипторе сегмента. Каждый раз, когда одна из этих проверок терпит неудачу, возникает исключение (прерывание) 13 (шестнадцатеричный 0D). Это исключение называется общей неисправностью защиты (GPF).

Это 13соответствует тому, что мы видели в файлах заголовков, так что похоже на то же самое. Однако с точки зрения прикладного программиста это просто означает, что мы ссылаемся на память, которой не должны быть, и на самом деле не имеет значения, как она реализована на оборудовании.

trojanfoe
источник
1
Однако современные ОС не используют сегменты для защиты памяти в целом. Все это делается с помощью MMU и приводит к PF, вектору 14 (обычно отображается как «Ошибка сегментации»).
Матс Петерссон
16

Мне было интересно, почему это появилось во время моих модульных тестов.

Я добавил объявление метода в протокол, который включает throws; но потенциально бросающий метод даже не использовался в этом конкретном тесте. Включение зомби в тест звучало слишком сложно.

Оказалось, что чистка ⌘K сделала свое дело. Я всегда поражаюсь, когда это решает настоящие проблемы.

ctietze
источник
Это исправило это и для меня в Swift. Спасибо!
lwdthe1
8

У меня было аналогичное исключение в Swift 4.2. Я потратил около получаса, пытаясь найти ошибку в моем коде, но проблема исчезла после закрытия Xcode и удаления папки с производными данными. Вот ярлык:

rm -rf ~/Library/Developer/Xcode/DerivedData
Станислав Барановский
источник
2

В моем случае ошибка была выдана в Xcode при запуске приложения на симуляторе iOS. Хотя я не могу ответить на конкретный вопрос «что означает ошибка», я могу сказать, что помогло мне, возможно, это также поможет другим.

Решение для меня было Erase All Content and Settingsв симуляторе и Clean Build Folder...в Xcode.

Manuel
источник
1

У меня возникла эта проблема при выходе из представления (вернуться к предыдущему представлению).

причина была в том, что

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)
])

Измените, safeAreaLayoutGuideчтобы selfрешить проблему.

Значение выравнивает представление с ведущим, конечным, верхним и нижним супервизором вместо безопасной области)

nuynait
источник
0

Это случилось со мной, потому что Xcode, похоже, не понравился мне, используя одно и то же имя переменной в двух разных классах (которые соответствуют одному и тому же протоколу, если это имеет значение, хотя имя переменной не имеет ничего общего ни с одним протоколом). Я просто переименовал свою новую переменную.

Мне пришлось войти в сеттеры, где он вылетал, чтобы увидеть это во время отладки. Этот ответ относится к iOS

Стивен Дж.
источник
0

Если ошибка возникает внутри замыкания, которое определяется selfкак unowned, вы можете быть ограничены в том, что вы можете получить, и получите этот код ошибки в определенных ситуациях. Особенно при отладке. Если это так, попробуйте перейти [unowned self]на[weak self]

Matjan
источник
0

Я получил эту ошибку при этом:

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

Он исчез, когда я вернулся к:

NSMutableDictionary *aDictionary=[[NSMutableDictionary alloc] init];
[aDictionary setObject:object1 forKey:@"Key1"]; //17 times
Питер Б. Крамер
источник
0

Для меня это проблема, связанная с раскадровкой, есть возможность сборки ViewController для iOS 9.0 и более поздних версий, ранее установленных для iOS 10.0 и более поздних версий. На самом деле я хочу понизить версию с 10 до iOS 9.3.

Анил Кумар
источник