Хранение объектов в стеке - PullRequest
3 голосов
/ 09 августа 2011

Можно ли выделить место для объектов в стеке? Я не хочу оспаривать принципы языка, и да, пулы авто-релизов работают очень хорошо. Это просто вопрос любопытства (и исследования этого). Я слышал о вещах как:

struct {
    Class isa;
} s_obj;

s_obj.isa = [NSObject class];

NSObject *obj = (NSObject *)&s_obj;

Но я не уверен, что это будет работать правильно. По крайней мере, это звучит не очень практично, поскольку структуру объекта необходимо будет заново создать.

Может быть, перезаписать +alloc и как-то вызвать alloca() за сцены? Похоже, что прохождение другой зоны в allocWithZone: будет лучший подход, но NSZone довольно недокументирован. CocoaDev имеет статью на этом, но опять же я не уверен, что это путь. Есть идеи?

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

Ответы [ 2 ]

5 голосов
/ 09 августа 2011

Нету; не могу этого сделать. Или, технически, вы можете , но вы не можете передать объект в любой системный API, и вы не можете подкласс NSObject.

Система предполагает, что объект находится в куче; autorelease будет работать так, как ожидается, а срок службы объекта можно контролировать, управляя сохраненной ссылкой, ни одна из которых не будет истинной для объекта, выделенного в стеке.

(Есть одно исключение; блоки начинаются в стеке. Иногда это особый случай, и он полностью контролируется компилятором. Он также сбивает людей с толку.)

<Ч />

alloca() не будет работать; память будет «выделена» (указатель стека будет увеличен) в кадре, который сделал выделение. Как только вы попытаетесь вернуть объект, выделение будет пустым, а возвращаемая ссылка станет висящим указателем.

NSZone устарел во всех, кроме декларации. OpenStep пытался увековечить распределение по зонам с целью быстрого уничтожения еще в 1994 году или около того. Оказалось слишком хрупким; было слишком много способов, которыми ссылка на зону могла бы проникнуть в другую зону, а разрушение зоны могло бы привести к появлению висящих указателей.

<Ч />

Запись того, что было в комментариях к вопросу Даниила

  • Как только стековый фрейм, содержащий выделенный стековый объект, уничтожается, любые ссылки на этот объект становятся недействительными. Таким образом, любые сообщения с любыми ссылками будут иметь неопределенное поведение и, скорее всего, в лучшем случае вылетят. То есть вы не можете установить для retain count какое-то сверхвысокое значение, потому что вызов release уже слишком поздний, поскольку он будет разыменовываться через недопустимую ссылку на объект, чтобы попытаться получить isa, чтобы попытаться выполнить метод .

  • Вы не можете подкласс NSObject в таком объекте, потому что NSObject несет в себе множество функциональных возможностей, как общедоступных, таких как KVO, KVC, и связанных объектов, так и различные частные детали реализации системных платформ. Любая из этих функций может свободно сохранять / освобождать / автоматически освобождать экземпляр в любое время, поскольку , в основном retain, гарантирует срок жизни объекта до release при создании подкласса NSObject .

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

0 голосов
/ 09 августа 2011

Теоретически вы можете получить кусок стекового хранилища (например, char[NN]) и передать его в init. [Или, может быть, нет - непонятно, как код решает, какой init вызвать - может потребоваться сначала установить класс, по крайней мере.] Что неизвестно (и недокументировано / не поддерживается), в какой степени остальная часть кода зависит от того, что делает инициализация alloc. Конечно, счетчик ссылок не будет действительным (и, вероятно, должен как-то быть инициализирован большим значением). Конечно, dealloc не будет вызываться при выходе из фрейма, и его сокращенную версию нужно будет вызывать явно.

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