Цель - C Причудливые причуды - PullRequest
0 голосов
/ 17 января 2020

В интерфейсе класса я определяю некоторый ivar

@property (strong,nonatomic) id < Protocol > initEst;   // Initial estimate

Это компилируется без проблем, но при запуске программы происходит сбой с EXC_BAD_ACCESS и [Object .cxx_destruct] указано отладчиком в качестве причины.

Что происходит?

Ответы [ 2 ]

1 голос
/ 17 января 2020

Все дело в правилах AR C automati c управления памятью. Инициализатор имеет специальные правила для того, как он обрабатывает возвращаемое значение: он сохраняет и возвращает. См. https://clang.llvm.org/docs/AutomaticReferenceCounting.html#semantics -of-init .

Objective- C в целом и AR C в частности, есть довольно строгие правила относительно того, что означают имена методов. initXXX означает «это инициализатор». Если это не инициализатор, не используйте префикс init.

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

1 голос
/ 17 января 2020

Я проверил это еще несколько раз, и, кажется, три условия для этой конкретной причуды, чтобы показать.

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

Итак, уточним мой предыдущий ответ. Если

  1. initXXX является иваром
  2. типа id типа
  3. , который реализует Protocol, который является таким же , как содержащий класс

, затем компилятор Objective- C + AR C успешно скомпилирует код, но не сможет его выполнить.

Вот пример кода Раньше я тестировал

@interface Dog : NSObject < Animal >

@property (nonatomic,strong) id < Animal > initState;

@end

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

Для справки, сгенерированная ошибка времени выполнения:

Объект Dog перевыпущен при освобождении

Этот фрагмент довольно абстрактно, но это может укусить вас в тех местах, где вам нужно указать какое-то начальное условие и где естественно назвать какой-то ivar initXxx, но будьте осторожны, если вы используете Objective- C, у вас нет такой роскоши, как и компилятор предупреждаю вас, что это неправильно.

Первоначальная ошибка казалась связанной с выделением памяти и заставила меня подозревать, как я использовал autoreleasepool , но теперь я совершенно уверен, что это не имеет ничего общего с выпуск.

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