Що є надійним способом зробити збій програми для iOS?


136

Я хочу перевірити звітність про аварійну ситуацію в моєму додатку, навмисно наклавши на нього аварію, коли користувач виконує певну дію, яку справжній користувач навряд чи здійснить випадково.

Але який хороший надійний спосіб зробити збій програми, який не створює попередження під час компіляції?

Редагувати: Зауважте, що багато, здавалося б, очевидних відповідей на це питання призводять до винятків, які потрапляють на какао і, таким чином, не призводять до збоїв у програмі.


Я отримую WebKit discarded an uncaught exceptionза всі ці ідеї поки що! Хто знав, що настільки важко зробити аварію програми сьогодні?
Нестор

Я не думаю, що жодне з них не має нічого спільного з WebKit ...
BoltClock

23
Так, відкрийте Safari на iPad 1 та перейдіть на сторінку з великою кількістю зображень. Завжди працює на мене. : /
Алан Б

4
(void)0/0;,(void)*(char*)0;
Кевін

1
Будьте обережні з деякими відповідями тут, посилаючись на невизначене поведінку . Це насправді дуже неприємна порада!
usr

Відповіді:


140

в Objective-C використовуйте C безпосередньо, щоб спричинити поганий доступ

strcpy(0, "bla");

Примітка. Хоча це працює в будь-якій системі, яку я знаю - у майбутній версії C виконання програми або компілятора це може більше не призвести до збоїв. див. Чи невизначена поведінка вказівника перенавантаження в Objective-C? )

(швидко вам доведеться перейти до objC, щоб це зробити)


це ІМХО найнадійніший спосіб
Міхал Крефт

Ага так, це WebKit discarded an uncaught exceptionтеж обходить проблему.
Нестор

ще був друкарський
помилок

4
Мабуть ( stackoverflow.com/questions/13651642/… ), це невизначена поведінка і насправді дуже погана відповідь! Компілятор може юридично оптимізувати обидва висловлювання і просто нічого не робити. Я пропоную вам видалити цю відповідь. Це може призвести до того, що люди дійсно роблять це.
usr

3
на ios, osx та windows та redhat він завжди вийшов з ладу, тому в даному контексті я б сказав, що він дійсний. Я додам відмову від відповідальності
Daij-Djan

97

Мій поточний фаворит:

assert(! "crashing on purpose to test <insert your reason here>");

Класичний:

kill( getpid(), SIGABRT );

І деякі pr0n:

*(long*)0 = 0xB16B00B5;

Усі вони генерують збої, зняті моїм інструментом звітності про аварії.


14
assert не виходить з
ладу у

6
це залежить від налаштувань збірки; Крім того, я думаю, що питання стосується тестування, здається, добре тримати твердження в тестових
складах

3
Дуже багато людей (включаючи мене) залишають твердження у версії версій. Немає підстав відключати їх.
Султан

5
@Sulthan: assert()це налагоджувальна функція, мало сенсу залишати таку сукупність у версії версій. Для цього є одиничні тести.
MestreLion

18
IMHO assertне є функцією налагодження. Невдале ствердження - помилка, яку ви вважали неможливою. Краще перервати навіть збірку релізів, ніж продовжувати запускати програму з непередбачуваними наслідками.
djromero

27

Оскільки ми всі використовуємо Clang для iOS, це досить надійно:

__builtin_trap();

Це має ту перевагу, що він розроблений саме для цієї мети, тому він не повинен створювати попередження або помилки компілятора.



22

Як щодо хорошого переповнення старого стека :)

- (void)stackOverflow
{
    [self stackOverflow];
}

16

Найпопулярніший - невпізнаний збій селектора:

NSObject *object = [[NSObject alloc] init];
[object performSelector:@selector(asfd)];

Переконайтеся, що у вас не використовується метод -asdf у цьому класі ха-ха

Або індекс за межами виключення:

NSArray * array = [NSArray array];
[array objectAtIndex:5];

І звичайно kill( getpid(), SIGABRT );


12

Я думаю, що в Swift ви могли легко нанести фатальну помилку:

func foo() {
    fatalError("crash!")
}

Насправді навіть призначено використовувати цю функцію у випадку, якщо щось піде не так, щоб збити програму.

Щоб уникнути оператора if у спеціальному випадку, ви також можете використовувати precondition. Це схоже на assert, робить таким чином намір (за бажанням) досить зрозумілим і не видаляється в остаточному релізі як assert. Він використовується як precondition(myBoolean, "This is a helpful error message for debugging.").


9

Надішліть повідомлення розміщеному об’єкту


34
Це насправді дуже ненадійно. Ви все одно можете надсилати повідомлення до розміщених об'єктів, доки їх пам'ять не буде використана повторно. Це вся причина, чому людям історично було важко налагоджувати помилки подвійного випуску. Лише тоді, коли пам'ять буде відтворена іншим об'єктом, пересилання повідомлення може спричинити виняток.
Майк Веллер

7
exit(0);

(повинен ... введіть ... 30 символів)


Дякую за оновлення, але насправді це змусить програму припинити роботу та повернутися до Springboard, який, хоча сам по собі може бути корисним, не є тим, що хотів ОП, а це спровокувати незавершене виключення
Стів Роджерс

6

Ви також можете підняти виняток:

[NSException raise:NSInternalInconsistencyException
            format:@"I want to test app crashes!."];

2
Я не думаю, що виняток є таким хорошим способом, коли вилучення є винятком, тому ви можете випадково його зловити. Ловля сигналів не така поширена, тому поганий доступ або подібні речі були б більш надійними. :)
Michał Kreft

3

Додайте розпізнавальник жестів до подання, яке розпізнає дотик на 10 пальців (5 пальців для iPhone, як 10, можуть трохи переповнитися). У GR є приєднаний до нього метод, який виконує будь-який із згаданих раніше надійних способів змусити ваш додаток до збоїв. Більшість користувачів не збираються класти 10 пальців на ваш додаток, тож ви захищені від загального користувача, який випадково спричинить збій.

Однак ви повинні мати можливість використовувати щось на кшталт Testflight або просто розгортати його на особистих пристроях і тестувати в природі, перш ніж подавати його в Apple. Примусовий збій може призвести до відхилення вашої програми Apple.


Мій додаток Cocos2d виходить з ладу, коли я роблю екстремальний мультитакт, і це я сприймаю як невирішену помилку. У мене немає жодної GR, але я включив мультитач в Cocos2d. Я відчуваю крах, який ви описуєте? Ви маєте на увазі, що така поведінка очікувана / розшукова?
Фредрік Йоханссон

@Fredrik Я не думаю, що очікується крах, який ви описуєте (збоїв ІМО ніколи не слід очікувати, і я особисто не думаю, що це було б гарною ідеєю цілеспрямовано помістити його у свій додаток з цього приводу). Ви можете спробувати символізувати збій і дізнатися, який саме метод спричиняє збій програми. Це може бути щось в рамках Cocos2d, що спричиняє аварію, коли виникає "екстремальний мультитакт". Якщо це так, то найкраща ставка - це подання помилок з хлопцями Cocos2d.
jhelzer

2

міг спробувати щось подібне

NSArray* crashingArray = [NSArray arrayWithCapacity:1];
[crashingArray release];

має вийти з ладу на EXC_BAD_ACCESS (можливо, потрібно буде випустити його вдруге, але, як правило, він повинен вийти з ладу, як це вже)


3
Немає компіляції з включеною ARC.
vikingosegundo

добре, якщо ви використовуєте ARC, ви також можете це зробити: NSArray * crashingArray = [NSArray arrayWithCapacity: 1]; [crashingArray objectAtIndex: 0]; це повинно бути
збоєм


0

Я б просто вбив процес нормально:

kill(getpid(), SIGKILL);

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


це вже включено у відповідь
madmw

0

я використовую

[self doesNotRecognizeSelector:_cmd]; 

2
Ця публікація автоматично позначена як низька якість, оскільки це лише код. Ви не хочете розширити його, додавши текст, щоб пояснити, чому це вирішує проблему?
gung - Відновіть Моніку



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