Objective-C невыделенный указатель - PullRequest
0 голосов
/ 05 февраля 2011

Я путаю ноль в target-C, потому что apple сказала, что можно отправлять сообщение объекту nil.

поэтому предположим, что этот код:

Foo * myFoo;
[myFoo doSomeStuff];

в XCode это не дает сбой, так почему? делает нераспределенный указатель в target-C таким же, как nil.

Спасибо.

Ответы [ 2 ]

3 голосов
/ 05 февраля 2011

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

3 голосов
/ 05 февраля 2011

Потому что есть разница между nil и random garbage. Вы видите, эта строка:

Foo * myFoo;

не дает никаких гарантий для значения myFoo, если вы явно не установите его. Попробуйте сами:

Foo* myFoo;
printf("%x\n", myFoo);

Вполне вероятно, что он не будет печатать 0; вместо этого он напечатает последнее, что произошло в этом месте памяти. (Это может быть нулем. Но очень хорошо, что не может быть.)

Локальные переменные имеют неопределенное значение, прежде чем назначать их самостоятельно. Во время выполнения Objective-C вызовы nil будут работать, но значение nil строго определено равным нулю: поэтому для использования этой функции вы должны инициализировать переменные nil (в противном случае вы, вероятно, ошибка сегментации, потому что передача случайного адреса не подходит для вашей программы).

Это всегда будет «работать» (под «работой» я имею в виду не крах):

Foo* myFoo = nil;
[myFoo whatever];

Вот пример программы, которая на моей машине постоянно не имеет нулевых указателей:

#include <stdio.h>
#include <string.h>

struct random_stuff
{
    int stuff[60];
};

struct random_stuff scramble()
{
    int filler = 0xdeadbeef;
    struct random_stuff foo;

    memset_pattern4(&foo.stuff, &filler, sizeof foo);
    return foo;
}

void print()
{
    void* pointer[30];
    for (int i = 0; i < 30; i++)
        printf("%p\n", pointer[i]);
}

int main()
{
    scramble();
    print();
}
...