Як знайти причину помилки «подвійного звільнення» від malloc?


80

Я програмую програму в Objective-C, і я отримую цю помилку:

MyApp (2121,0xb0185000) malloc: *** помилка для об'єкта 0x1068310: подвійний безкоштовний
*** встановити точку зупинки в malloc_error_break для налагодження

Це відбувається, коли я випускаю NSAutoreleasePool, і я не можу зрозуміти, який об'єкт я випускаю двічі.

Як встановити його точку зупинки?

Чи можна дізнатися, що це за "об'єкт 0x1068310"?


3
можливо, ви захочете позначити цю публікацію і на iPhone, щоб залучити ще кілька людей
Бенні Вонг,

4
Вилучено тег "iphone" на користь інших більш відповідних тегів.
Quinn Taylor

3
Я не уявляю, чому в цьому запитанні iPhone бракує тегу iPhone. Людей, які стежать за "iPhone", повинно бути більше, ніж деякі з цих інших тегів, таких як "автовипуск". Якщо ви хочете знайти "автовипуск", ви шукаєте його, ви не стежите за тегом. Тож я повернув "iPhone" назад.
Носредна

6
Причиною того, що я видалив тег "iphone", є те, що ніщо в цьому питанні не стосується iPhone. Єдине посилання взагалі полягає в тому, що це відбувається в додатку для iPhone, але точно така ж помилка може виникнути в будь-якому додатку C або Objective-C. Я не сподіваюся, що люди, які стежать за iPhone, будуть випадково зацікавлені в цьому - скоріше, це будуть люди, які шукають такі речі, як "подвійний безкоштовний" або "malloc_error_break", і якщо вони кинуть в "iPhone", це все одно з'явиться . Не будемо сперечатися щодо тегів, але врахуймо, що, можливо, люди, які відповідають, можуть знати, де саме питання найкраще належить.
Quinn Taylor

3
Це питання принаймні стосується какао. Якщо тег iPhone ображає, як щодо тегу какао? Очевидний намір стосується Objective-C на какао в XCode. Не Objective-C у Windows, Linux або поза контекстом XCode.
runako

Відповіді:


38

Що це за об’єкт, ви дізнаєтесь, коли зламаєте налагоджувач. Просто знайдіть стек дзвінків, і ви знайдете, де ви звільняєте його. Це підкаже, який це об’єкт.

Найпростіший спосіб встановити точку зупинки:

  1. Перейдіть до пункту Виконати -> Показати -> Точки зупинки ( ALT- Command- B)
  2. Прокрутіть до кінця списку та додайте символ malloc_error_break

1
Я спробував це, але я отримую: неможливо знешкодити malloc_error_break .... що це означає?
gonso

3
Немає допомоги для автовипуску подвійного безкоштовно. Йому потрібні зомбі
Рог,

58
@gonso - Просто цікаво, якщо це у вас не спрацювало, чому ви прийняли це як відповідь?
Квін Тейлор

8
У Xcode 4.3.2 точки зупинку можна знайти у меню Перегляд → Навігатори → Показати навігатор точок зупинки або №6 (Cmd-6)
Андреас Лей

46

Коли об’єкт «подвійно звільнений», найпоширенішою причиною є те, що ви (без потреби) випускаєте автоматично випущений об’єкт, а пізніше він автоматично випускається, коли пул, що містить автоматичний випуск, звільняється.

Я виявив, що найкращим способом відстежити додатковий випуск є використання змінної середовища NSZombieEnabled для відповідного виконуваного файлу в Xcode. Щоб швидко ознайомитись із цим , перегляньте цю вікі-сторінку CocoaDev . (На додаток до цієї сторінки, Apple задокументувала неймовірно незрозумілі, але корисні поради щодо налагодження коду в Xcode, деякі з яких зберегли мій бекон більше ніж кілька разів. Пропоную ознайомитися з цим Технічним зауваженням на developer.apple.com - посилання переходить до розділу про основи фонду Какао).

Редагувати: Ви часто можете відслідковувати об’єкт-порушник у налагоджувачі Xcode, але часто набагато простіше, якщо ви використовуєте інструменти, щоб допомогти вам. У Xcode виберіть Виконати → Почати з інструмента продуктивності → Розподіл об’єктів, і ви зможете простежити об’єкт-порушник назад, де він був створений. (Це найкраще буде працювати, якщо ви активували зомбі, як обговорювалося вище.) Примітка. Snow Leopard додає інструмент Zombies до інструментів, доступний також із меню Run. Може коштувати лише 29 доларів США! ;-)

Тут також є відповідне запитання SO .


1
Сторінка вікі CocoaDev, на яку посилається у відповіді, мертва :(
Devarshi

Використовуйте машину для зворотного шляху: web.archive.org/web/20120325135712/http://www.cocoadev.com/…
Квін Тейлор

12

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

В одному зі своїх додатків я повинен аналізувати та зберігати дані в основних об’єктах даних, а пізніше отримувати ці об’єкти для відображення у поданнях. Насправді додаток працює чудово і абсолютно не виходить з ладу, поки я не спробував зробити стрес-тест навігації вперед і назад кілька разів, не спробував якомога швидше відкрити кілька подань. Додаток аварійно завершує роботу із зазначеним вище повідомленням.

Я випробував усі методи, запропоновані Квін у своїй відповіді, і досі не зміг з’ясувати, де саме була причина.

Я встановив NSZombieEnabled = YES та NSStackLogging = YES, запустив командну оболонку malloc_history, щоб з'ясувати причину, але все одно не пощастило. Це завжди вказує на те, куди я зберігаю дані в основних об’єктах даних, насправді я перевірив тисячі разів над звільнені об’єкти там, нічого дивного.

Запуск в Інструментах з різними інструментами (розподіли, витоки тощо ...) все одно не допоміг. Включити Guard Malloc все ще нічого не отримав.

Остаточне порятунок: Я спробував повернутися до видів, де об’єкти були взяті з Основних даних, і надіслав повідомлення про збереження всім цим об’єктам, і взяв до відома ці зміни. Це вирішило проблему !!!

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


9

Відкрийте консоль налагоджувача, натиснувши Cmd + Shift + R. Там наберіть

break malloc_error_break

щоб встановити точку зупинки на початку malloc_error_breakфункції.

Якщо ви хочете дізнатись, який об’єкт знаходиться за адресою 0x1068310, ви можете ввести в консоль налагоджувача таке:

print-object 0x1068310

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


Це автовипуск, йому потрібні зомбі.
Рог,

1
Нарешті, я зробив виклик методу "підозрілого" поза AutoreleasePoll. Забавно думав, що я все-таки отримав попередження, але жодної точки перерви не вдарили. Я просто коментував блоки, поки не знайшов рядок. Я автоматично випускав рядок, створений за допомогою stringWithFormat (без розміщення або копіювання). Дякую усім за поради! Гонсо
гонсо

Для цього конкретного типу помилок злом malloc_error_break ніколи не допомагав знайти проблему - він завжди вимагав включення зомбі.
Квін Тейлор

Дивіться тут для отримання інструкцій з налаштування контрольної точки для malloc_error_break в XCode 4: stackoverflow.com/questions/6969407 / ...
benvolioT

1
@Zammbi: Спробуйте використовувати poпсевдонім або еквівалентно expr -o. За роки з моменту написання цієї відповіді механізм налагодження, який використовував Xcode, був змінений з GDB на LLDB, і LLDB має інший набір команд.
Адам Розенфілд,

4

Для мене це питання вирішив

(gdb) call (void)_CFAutoreleasePoolPrintPools()

відразу після аварії. Адреса у верхній частині стопки була адресою винного. Кинув в retainі вуаля.

Адреса, вказана в журналі, нікуди не дійшла. Він ніколи не з'являвся в жодному з різних інструментів. Мабуть, вказівник на деякі внутрішні дані, які вже були звільнені.


4

Додавання символічної точки зупинки в Xcode 4

Просто оновлення, щоб зробити це актуальним для Xcode 4 ...

З посібника користувача Xcode 4 :

Щоб додати символічну точку зупинки. . .

  1. У нижньому лівому куті навігатора точки зупинку натисніть кнопку Додати.
  2. Виберіть Додати символічну точку зупинки.
  3. Введіть ім'я символу в поле Символ.
  4. Натисніть Готово.


2

Перевірте свої заняття та подивіться на метод dealloc. Обов’язково телефонуйте[super dealloc].

У мене була така сама проблема, і я дізнався, що [self dealloc]натомість телефоную . Просто не звертаючи уваги.


2

Будь ласка, знайдіть наведені нижче кроки, як знайти безкоштовний об’єкт та вивести з ладу програму.

1) Клацніть на " Навігатор точки зупинку ".
2) Потім натисніть на кнопку " + ", яка знаходиться внизу.
3) Додайте зі списку " Символічну точку зупинки ... ".
4) Додайте ключове слово " malloc_error_break " до параметра " Символ ".

Або ви також можете звернутися до поданої нижче презентації GIF.

Представлення GIF


1

Зазвичай це спричиняє якийсь інспектор, наприклад, сафарі чи попередній перегляд сафарі. Зверніться до допису або допису та запитання .

Видаліть позначку Автоматично показувати веб ...., видалить цю проблему.

Зауважте, що просто закривши сафарі або попередній перегляд сафарі, ця проблема не буде усунена. І вам доведеться скасувати вибір як для сафарі, так і для попереднього перегляду сафарі.

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

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


0

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

Рекомендується не мати об’єкта, який ви створюєте, autoreleaseоскільки пам’ять - це товар на iPhone. Apple рекомендує чітко телефонувати release.


0

Щоб знайти подібні проблеми з пам'яттю та вказівниками загалом, потрібно запустити свій код за допомогою перевірки помилок пам’яті часу виконання, як Valgrind . Це повинно мати можливість вказувати на багато речей, які ваш код робить неправильно, крім тих, що спричиняють його збій.

Valgrind може працювати на OSX (хоча там сказано, що він "не підтримується, неповний і помилковий"), і з невеликим злом хтось змусив його працювати на виконуваних файлах iPhone SDK .

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


1
інструменти - це шлях; скористайтеся інструментом розподілу об’єктів і увімкніть зомбі. (або просто скористайтеся шаблоном Zombies). Valgrind - це рішення в крайньому випадку. Це надзвичайно повільно і часто просто не працює.
bbum

0

Якщо malloc_error_breakне допомагає ...

Найкращий спосіб вирішити цю помилку - запускати інструменти з NSZombiesувімкненим режимом. Інструменти позначать вас, коли буде надіслано повідомлення про зомбі, і ви зможете перейти безпосередньо до рядка коду.

Сніговий барс потрібен, яка ж рятівниця!

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