Как найти причину ошибки "double free" malloc?

Я программирую приложение в Objective-C, и я получаю эту ошибку:

MyApp (2121,0xb0185000) malloc: & ast; ** ошибка для объекта 0x1068310: double free
    *** установить точку останова в malloc_error_break для отладки

Это происходит, когда я выпускаю NSAutoreleasePool, и я не могу понять, какой объект я выпускаю дважды.

Как установить его точку останова?

Есть ли способ узнать, что это за "объект 0x1068310"?

Ответ 1

Вы узнаете, что представляет собой объект, когда вы ломаетесь в отладчике. Просто найдите стек вызовов, и вы найдете, где его освободите. Это скажет вам, какой именно объект.

Самый простой способ установить точку останова:

  • Перейдите в Run → Show → Breakpoints (ALT - Command - B)
  • Прокрутите список до конца и добавьте символ malloc_error_break

Ответ 2

Когда объект является "дважды освобожденным", наиболее распространенной причиной является то, что вы (ненужно) освобождаете объект с автореализацией, и позже он автореализован, когда пул резервных копий пуста опустеет.

Я обнаружил, что лучший способ отследить дополнительный выпуск - использовать переменную среды NSZombieEnabled для уязвимого исполняемого файла в Xcode. Для краткого изложения того, как его использовать, просмотрите эту страницу вики CocoaDev. (В дополнение к этой странице Apple задокументировала некоторые невероятно неясные, но полезные советы по отладке кода в Xcode, некоторые из которых сохранили мой бекон более чем несколько раз. Я предлагаю проверить это Техническое примечание на developer.apple.com - ссылка переходит в раздел Cocoa Foundation framework).

Изменить: Вы можете часто отслеживать оскорбительный объект в отладчике Xcode, но часто это намного проще, если вы используете инструменты, чтобы помочь вам. Из Xcode выберите Run → Начните с Performance Tool → Object Allocations, и вы сможете отслеживать объект-нарушитель обратно туда, где он был создан. (Это будет работать лучше всего, если вы включили зомби, как описано выше.) Примечание. Snow Leopard добавляет инструмент Zombies для инструментов, доступный из меню "Выполнить". Может стоить только $29!; -)

Здесь также существует связанный вопрос SO.

Ответ 3

Я просто хочу добавить свой опыт в дополнение к ответу Куинна Тейлора.

В одном из моих приложений мне приходится анализировать и сохранять данные в основных объектах данных, а затем получать эти объекты для отображения в представлениях. На самом деле приложение работает нормально и вообще не сбой, пока я не попытался выполнить стресс-тест по навигации взад и вперед несколько раз, попытался как можно быстрее открыть несколько просмотров. Приложение вылетает с указанным выше сообщением.

Я пробовал все методы, предложенные Куинном в его ответе, и до сих пор не смог выяснить, где была точная причина.

Я установил NSZombieEnabled = YES и NSStackLogging = YES, запустил командную оболочку malloc_history, чтобы узнать, почему, но все равно не повезло. Он всегда указывает на то, где я сохраняю данные в основных объектах данных, на самом деле, я проверил тысячу раз над выпущенными объектами, ничего странного.

Работа в Инструментах с различными инструментами (Распределение, Утечки и т.д.) все еще не помогла. Включить Guard Malloc все равно ничего не получилось.

Окончательное спасение: я попытался вернуться к представлениям, в которых объекты были взяты из Core Data, и отправил сообщение сохранения всем этим объектам и принял к сведению эти изменения. Он решил проблему!!!

Итак, я узнал, что я не смог сохранить его, что именно причина. Просто хочу поделиться своим опытом, чтобы у вас было другое спасение для вашего приложения.

Ответ 4

Откройте консоль отладчика, нажав Cmd + Shift + R. Там введите

break malloc_error_break

чтобы установить точку останова в начале функции malloc_error_break.

Если вы хотите узнать, какой объект находится по адресу 0x1068310, вы можете ввести следующее в консоль отладчика:

print-object 0x1068310

Конечно, вы должны сделать это, пока объект все еще жив - если объект уже был освобожден к тому моменту, когда вы это сделаете, это не сработает.

Ответ 5

Для меня проблема была решена с помощью

(gdb) call (void)_CFAutoreleasePoolPrintPools()

сразу после аварии. Адрес в верхней части стека был адресом виновника. Бросил a retain и вуаля.

Адрес, указанный в сообщении журнала, не доставил меня никуда. Он никогда не появлялся ни в одном из различных Instrumets. По-видимому, указатель на некоторые внутренние данные, которые уже были освобождены.

Ответ 6

Добавление символьной точки останова в Xcode 4

Просто обновление, чтобы сделать это применимым к Xcode 4...

Из Руководство пользователя Xcode 4:

Добавить символическую точку останова.,.

  • В левом нижнем углу навигатора точки останова нажмите кнопку Добавить кнопка.
  • Выберите Добавить символическую точку останова.
  • Введите имя символа в Поле символов.
  • Нажмите "Готово".

Ответ 8

Проверьте свои классы и посмотрите на метод dealloc. Удостоверьтесь, что вам нужно позвонить [super dealloc].

У меня была такая же проблема и выяснилось, что я звонил [self dealloc]. Просто не обращая внимания.

Ответ 9

Обычно это вызвано некоторым инспектором, таким как предварительный просмотр сафари или сафари. Обратитесь к сообщению или сообщению и вопрос.

Удалите выбор AutoMatically Show Web...., удалите эту проблему.

Примечание. Простое закрытие сафари или предварительного просмотра сафари не устранит эту проблему. И вы должны отменить выбор сафари и сафари.

Если этого не произойдет, обратитесь к этому сообщению или post, чтобы отладить его.

отменить автоматическую проверку предварительного просмотра сафари

Ответ 10

Ниже вы найдете инструкции по тому, как найти свободный объект и свернуть приложение.

1) Нажмите " навигатор точки останова".) 2) Затем нажмите " +", которая находится ниже.
3) Добавьте символ Символический Точка останова... "из списка.
4) Добавьте" malloc_error_break" в опции Символ.

Или вы также можете обратиться к ниже представленной презентации GIF.

GIF represenation

Ответ 11

В Xcode нажмите левую часть номера строки, чтобы установить точку останова. Затем вы можете запустить его, выполнив "Построение и отладка".

Рекомендуется не создавать объект, который вы создаете, autorelease, так как память является товаром на iPhone. Apple рекомендует явно называть release.

Ответ 12

Чтобы найти такие проблемы с памятью и указателями в целом, вы хотите запустить свой код с помощью проверки ошибок памяти во время выполнения, например Valgrind. Это должно указывать на то, что ваш код делает неправильно, помимо тех, которые приводят к его сбою.

Valgrind может работать на OSX (хотя он говорит, что он "неподдерживаемый и неполный и багги" ), и с небольшим взломом кто-то его получил для работы над исполняемыми файлами iPhone SDK.

Еще лучше вы можете попробовать инструменты, которые являются частью XCode. Там учебник для запуска здесь.

Ответ 13

Если malloc_error_break не помогает...

Лучший способ решить эту ошибку - запустить инструменты при включенном NSZombies. Инструменты будут отмечать вас, когда Zombie отправлен в сообщение, и вы можете напрямую отследить строку кода.

Требуется Snow Leopard, какой спасатель!