Как объекты Objective-C защищены? - PullRequest
0 голосов
/ 10 марта 2012

В моем предыдущем вопросе я выяснил, что все объекты Objective C объявлены как указатели.Но в C и C ++ к указателям можно обращаться из любой функции, глобальной или нет, и они кажутся незащищенными.

Как они «защищены» в Objective-C?

Ответы [ 3 ]

2 голосов
/ 10 марта 2012

ObjC не контролирует использование вами указателей.

Существует проверка типов во время компиляции, поэтому, если у вас есть указатель на NSNumber, и используйте переменную, которая содержит его, для присвоения NSString, компилятор выдаст предупреждение.Однако это легко можно переопределить, приведя указатель, как показано ниже,

NSNumber *myNumberPtr = [NSNumber initWithInt:99];

NSString *myStringPtr = (NSString *) myNumberPtr;

. В этом случае компилятору предписывается сохранять молчание, но доступ к myStringPtr в виде строки вызовет «неопределенные результаты».Надеюсь, что-то очевидное, например, сбой, но, возможно, что-то более пагубное.

Точно так же я мог бы заявить,

NSString *notActuallyAString = 0x897996789; // assigned some random value

Тогда, когда к 1011 * обращаются во время выполнения, это очень вероятновызвать исключение неправильного доступа, так как указатель почти наверняка не указывает на NSString и, вполне возможно, вообще не является допустимым адресом памяти.

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

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

Вам нужно хорошее понимание указателей для программирования в objC, и я бы порекомендовал прочитать классический вневременный справочник Kernighan & Ritchie 'The C Programming Language', в котором объясняются основыуказатели, вы можете построить понимание того, как указатели и распределение памяти используются в ObjC и C ++.

1 голос
/ 10 марта 2012

Указатель сам по себе не имеет никакой защиты.

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

В Objective-C члены защищены по умолчанию. Вот что обеспечивает защиту, которую вы ищете.

0 голосов
/ 10 марта 2012

В Objective-C переменные экземпляра по умолчанию не отображаются.В Objective-C 2.0 они предоставляются свойствами с использованием синтаксиса @property и @synthesize.(До версии 2.0, только с помощью явно написанных методов получения / установки.)

Несмотря на это, существует возможность прямого доступа к переменным экземпляра с использованием синтаксиса оператора указателя, например, NSString *bar = Foo->_text;, даже если text не отображаетсякак свойство.

Кроме того, теперь вы можете объявить переменные экземпляра в файле реализации, чтобы избежать их отображения в общедоступных заголовочных файлах.Если вы пишете каркасный код, это обеспечивает некоторую «защиту» от доступа к иварам вне средств доступа к свойствам, поскольку они больше не видны.

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