Как воспроизвести редкий сбой "_CFAutoReleasePoolPop"? - PullRequest
0 голосов
/ 28 октября 2019

Я пытаюсь воспроизвести такие ошибки: enter image description here

В моем проекте есть ручной подсчет ссылок. Кроме того, есть много многопоточности. Некоторые свойства не являются потокобезопасными. :(
У меня есть только одно предположение о причине этого сбоя: какой-то объект перевыпущен (?) .

Я добавил автоматические тесты пользовательского интерфейса (Appium),но они еще не помогли.
Кроме того, я профилировал для Zombies - все выглядит нормально.
Кроме того, я пробовал Статический анализатор Xcode (Product -> Analyze), там многопредупреждения, но ни одно из них не является причиной такого сбоя (я посмотрел на предупреждение Incorrect decrement of reference count not owned at this point).

Я создал тестовый проект с MRC и добавил такой код:

- (void)testAssumptions {
    //@autoreleasepool
    {
        [self overReleaseNilValue];
        [self overReleaseNotNilValue];
    }
}

- (void)overReleaseNilValue {
    NSIndexPath* path = [[NSIndexPath alloc] initWithIndex:42];
    [path release];
    [path release];
}

- (void)overReleaseNotNilValue {
    NSIndexPath* path = nil;
    [path release];
    [path release];
}

Двойное высвобождение объекта не приводит к сбою ни с включенным пулом автоматического выпуска, ни без пула.

Итак, мои вопросы:
1. Что может быть еще одной причиной такого сбоя кроме освобождения уже освобожденного объекта?
2. Существуют ли способы увеличить вероятность воспроизведения такого сбоя? Например, некоторая переменная env., Которая уменьшает некоторую толерантность пула автоматического выпуска к небезопасному коду? Или некоторыедополнительный пул авто-релизов?
3. Почему мой тестсбой кода oject?

Любые комментарии приветствуются.

1 Ответ

2 голосов
/ 28 октября 2019

Неправильное уменьшение счетчика ссылок, не принадлежащего на данный момент

Это определенно было бы предупреждением для изучения. Это почти наверняка указывает вам, по крайней мере, на одну ошибку.

Ваш тестовый проект на самом деле ничего не тестирует (я считаю, что они также названы в обратном направлении). Нет никаких обещаний, что чрезмерное освобождение значения вызовет сбой. overReleaseNotNilValue - это четко определенное поведение, которое абсолютно не вылетает (отправка сообщения на nil ничего не делает). overReleaseNilValue - неопределенное поведение. Я не копался в этом, но я ожидал бы, что NSIndexPath будет реализован с помощью теговых указателей, которые не будут аварийно завершаться, если вы их чрезмерно отпустите.

Undefined не определено. Это не значит крах. Чрезмерное освобождение значения может сделать что угодно. Если вам повезет, он рухнет ....

Кроме того, есть много многопоточности. Некоторые свойства не являются потокобезопасными.

Я бы ожидал, что это станет причиной вашей проблемы, если она будет прерывистой. Я работал над такими проектами. Решение состоит в том, чтобы исправить проблемы. Вы не будете знать, какая именно проблема является причиной ваших сбоев. Вы можете никогда не знать. Вы все еще должны исправить их все. Это займет некоторое время, но вы должны сделать код потокобезопасным, или его поведение не определено.

Что касается отладки, вам потребуется выполнить следующее в следующем порядке:

  • Включите параметры очистки времени выполнения (в редакторе схем, Выполнить, Диагностика). Для этого вам особенно понадобится дезинфицирующее средство для нитей.

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

  • Снимите все предупреждения. В вашем проекте должно быть ноль предупреждений. Если есть много «ложных» предупреждений, то вы никогда не увидите реальных предупреждений, точно указывающих, где ваши проблемы. Устраните все предупреждения.

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

...