EXC_BAD_ACCESS, но без зомби и не в конфигурации отладочной сборки - PullRequest
3 голосов
/ 27 мая 2009

Это сводит меня с ума. Я только что загрузил свое первое приложение в App Store в первый раз, и, конечно, теперь мое приложение взрывается влево и вправо. Когда я строю с конфигурацией сборки релиза, я случайно получаю EXC_BAD_ACCESS после того, как в течение некоторого времени стучу по приложению. Я снова включил Zombies, но проблема, похоже, не в том, что переменная перевыпускается, поскольку я не получаю сообщения об отправке сообщения в освобожденную переменную.

Ошибка всегда появляется в одном и том же месте в моем коде. Похоже, я пытаюсь сохранить переменную, которая не была правильно инициализирована. Я понятия не имею, как я мог это сделать.

Но вот странная вещь: если я собираю конфигурацию отладочного релиза, ЭТО НИКОГДА НЕ ПОКРЫВАЕТСЯ. Я могу стучать по этому предмету целый день, и он твердый. Я строю с конфигурацией выпуска, и все это периодически прерывается.

Глядя на настройки сборки в двух конфигурациях, различий не так много. При отладке уровень оптимизации GCC 4.0 равен «Нет», а в версии «Самый быстрый, самый маленький». Если я переключаю уровень оптимизации в Release на «None», приложение ведет себя само. Кто-нибудь знает, что я должен искать, чтобы это исправить? С другой стороны, сколько плохих вещей случится, если я распространю без оптимизации?

UPDATE:

Dang! Мне действительно нужен волшебный инструмент отладки для ошибок памяти. Я работал над этой проблемой последний день или около того. Я добавил exercise метод, который надежно генерировал бы сбой, и начал искать область кода, которая его вызывала.

Приложение обычно зависало в 3-5-й раз, когда я выполнял один конкретный тип операции. Единственное, что отличалось в этом типе операций, это значение, которое я возвратил из вспомогательного метода. Дополнительный метод обычно возвращал NSDecimalNumber s со значениями 0-3, но был один особый случай, когда я возвращал NSDecimalNumber с нецелым значением. Я бы протестировал результат вспомогательного метода в поиске нецелого значения. Я изменил специальный случай, чтобы он возвращал NSDecimalNumber со значением -1 вместо нецелого значения, и теперь я больше не могу вызвать сбой приложения.

По сути, единственное изменение, которое я сделал, это переключение с [[NSNumber numberWithDouble:num] decimalValue] -> авария в [[NSNumber numberWithInteger:num] decimalValue] -> без сбоев

Это немного, но сложнее, но не намного.

Теперь я рад, что приложение больше не падает, но внесенные мною изменения не внушают мне уверенности, так как старые фрагменты кода не выглядят «сломанными». Так что, хотя мое приложение больше не падает, это не потому, что я его «исправил», я просто изменил какую-то случайную вещь, и теперь она работает. 8 ^ (

UPDATE:

Отладчик не выдает трассировку стека, как это обычно происходит при сбое программы. В случае сбоя консоль отладки выдает следующее:

Загрузка программы в отладчик…

[... авторские права ...]

This GDB was configured as "i386-apple-darwin".warning: Unable to read symbols for "/System/Library/Frameworks/UIKit.framework/UIKit" (file not found).

warning: Unable to read symbols from "UIKit" (not yet mapped into memory).

warning: Unable to read symbols for "/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics" (file not found).

warning: Unable to read symbols from "CoreGraphics" (not yet mapped into memory).
Program loaded.

sharedlibrary apply-load-rules all

Attaching to program: `/Users/...', process 10066.

Re-enabling shared library breakpoint 1

Cannot access memory at address 0x4

Cannot access memory at address 0x4

(gdb) 

Ответы [ 2 ]

2 голосов
/ 27 мая 2009

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

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

Если вы можете привести его к сбою, обратите внимание на трассировку стека в качестве первого шага.

Нет ничего плохого в том, чтобы распространять без оптимизации, но это просто маскирует проблему. Там есть ошибка кодирования. Оптимизация не нарушает ваш код. Ваш код не работает.

Здесь хорошо обсуждается проблема отладки памяти здесь . Правило № 1 заключается в том, что вы должны использовать средства доступа. Они спасут вас от душевных страданий, так что, надеюсь, вы уже это сделаете. В моем кратком обсуждении правил управления памятью .

я привожу несколько других указателей.
1 голос
/ 27 мая 2009

Я бы посоветовал проверить уровень предупреждения на вашем компиляторе и посмотреть, появится ли что-нибудь. Откройте настройки вашего проекта и включите каждую опцию «предупреждение», которую вы можете найти. Или найдите настройку проекта с именем Другие флаги C и добавьте флаги -Wall -Wextra.

Вы получите много белого шума за такие вещи, как несоответствия со знаком / без знака, возможную потерю точности и т. Д., Которые вы можете (обычно) безопасно игнорировать Однако могут появиться некоторые ключевые предупреждения, которые вы определенно НЕ должны игнорировать: например, создание указателя из целого числа без приведения (или наоборот). Если вы не уверены на 100%, что можете игнорировать предупреждение, исправьте код, чтобы предупреждение исчезло.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...