Что означает код исключения "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