Що означає код винятку "EXC_I386_GPFLT"?


117

Що означає код винятку EXC_I386_GPFLT?

Чи змінюється його значення залежно від ситуації?

У такому випадку я маю на увазі тип EXC_BAD_ACCESSвиключення з кодом виключенняEXC_I386_GPFLT

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

Велике спасибі!

Відповіді:


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. Потім перейдіть до інструментів, щоб розпочати запис. Поверніться до своєї програми та спробуйте створити помилку. Прилади повинні виявляти поганий дзвінок (до зомбі), якщо такий є.

Сподіваюся, це допомагає!



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

Гаразд, значить, це загальна помилка захисту (як випливає з назви, що завгодно). Помилка загального захисту в ig6 "i386" дає багато звернень, але це виглядає цікаво:

Захист пам’яті також реалізований за допомогою дескрипторів сегмента. По-перше, процесор перевіряє, чи значення, завантажене в регістр сегмента, посилається на дійсний дескриптор. Потім він перевіряє, що кожна розрахована лінійна адреса фактично лежить в межах сегмента. Також тип доступу (читання, запис або виконання) перевіряється на предмет інформації дескриптора сегмента. Щоразу, коли одна з цих перевірок не вдається, виняток (переривання) 13 (шестнадцятковий 0D) піднімається. Цей виняток називається загальною помилкою захисту (GPF).

Це 13відповідає тому, що ми бачили у файлах заголовка, тому схоже на те саме. Однак, з точки зору програміста програми, це просто означає, що ми посилаємось на пам'ять, якою не повинна бути, і це не дуже важливо, як вона реалізована на апаратному забезпеченні.


1
Однак сучасні ОС взагалі не використовують сегменти для захисту пам'яті. Це все зроблено з MMU, і це призвело б до вектора 14 PF (зазвичай відображається як «помилка сегментації»).
Матс Пітерссон

16

Мені було цікаво, чому це з’явилося під час моїх тестових одиниць.

Я додав декларацію методу до протоколу, який включав throws; але потенційно метальний метод навіть не використовувався в цьому конкретному тесті. Увімкнення зомбі в тесті звучало як занадто багато проблем.

Виявляється, cleanK чисто зробив трюк. Мені завжди завгодно, коли це вирішує фактичні проблеми.


Це і зафіксувало це для мене у Свіфті. Дякую!
lwdthe1

8

У мене був подібний виняток у Swift 4.2. Я витратив близько півгодини, намагаючись знайти помилку в своєму коді, але проблема виникла після закриття Xcode та видалення отриманої папки даних. Ось ярлик:

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

2

У моєму випадку помилку було скинуто в Xcode під час запуску програми на тренажері iOS. Хоча я не можу відповісти на конкретне запитання "що означає помилка", я можу сказати, що мені допомогло, можливо, це також допомагає іншим.

Рішення для мене полягало Erase All Content and Settingsв тому, щоб в тренажері і Clean Build Folder...в Xcode.


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вирішити проблему.

Це означає, що вигляд вирівнюється з провідним, кінцевим, верхнім, нижнім, а не безпечним)


0

Це сталося зі мною, тому що Xcode, схоже, не подобається мені, використовуючи те саме ім’я змінної у двох різних класах (які відповідають одному і тому ж протоколу, якщо це має значення, хоча ім'я змінної не має нічого пов'язаного в жодному протоколі). Я просто перейменував свою нову змінну.

Мені довелося вступити в сетери, де воно врізалося, щоб побачити це, налагоджуючи. Ця відповідь стосується iOS


0

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


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.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.