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

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

Знает ли его значение в зависимости от ситуации?

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

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

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

Ответ 1

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

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

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

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

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

Ответ 2

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

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

ОК, так что это общая ошибка защиты (как ее название в любом случае предлагает). Googling "i386 общая ошибка защиты" дает много хитов, но этот выглядит интересным:

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

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

Ответ 3

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

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

Ответ 4

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

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

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

Ответ 5

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

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

Ответ 6

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

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

Ответ 7

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

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

Ответ 8

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

Ответ 9

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

 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