Ошибка: нулевое разыменование

Этот код:

int main(char[][] args)
{
  MyObject obj;
  obj.x;
  return 0;
}

дает мне: Error: null dereference in function _Dmain когда я компилирую его с флагом -O (на dmd2) Почему? Разве obj не выделено в стеке? Должен ли я всегда использовать new для создания объектов?


d
person szx    schedule 07.07.2010    source источник


Ответы (2)


Резюме: вам нужны новые объекты. Всегда.

Классы D ближе к C# или Java, чем к C++. В частности, объекты всегда всегда являются ссылочными значениями.

MyObject под капотом является указателем на фактический объект. Таким образом, когда вы используете MyObject obj;, вы создаете указатель null, а не объект. Объект должен быть создан с помощью оператора new:

auto obj = new Object();

Это создает объект в куче.

Вы не можете напрямую создавать объекты в стеке в D. Лучшее, что вы можете сделать, это что-то вроде этого:

scope obj = new MyObject;

Компилятору разрешено помещать объект в стек, но он не обязан.

(На самом деле, я подозреваю, что это может исчезнуть в будущей версии D2.)

Кстати, если вы используете D2, я считаю, что ваша основная функция должна выглядеть так:

int main(string[] args)
{
    ...
}

char[] и string имеют одинаковую физическую структуру, но означают немного разные вещи; в частности, string — это просто псевдоним для immutable(char)[], поэтому, используя char[], вы обходите защиту системы const.

person DK.    schedule 07.07.2010
comment
Итак... является ли MyObject *obj указателем на obj или двойным указателем на obj? т. е. могу ли я указывать указатели на объекты, если все в порядке? - person szx; 07.07.2010
comment
@serejko MyObject* obj был бы указателем на ссылку на объект, что, как правило, было бы очень странным. Как правило, вам не следует использовать указатели в D. Они есть, если они вам нужны, но они небезопасны и обычно вам не нужны. Я бы действительно посоветовал более подробно ознакомиться с документацией на сайте Digital Mars. А еще лучше, если вы можете себе это позволить, возьмите новую книгу Андрея Александреску Язык программирования D. В целом хорошо объясняет. - person Jonathan M Davis; 07.07.2010
comment
@DK scope в этом контексте определенно прекращается, насколько я понимаю, но на данный момент он все еще работает. Я полагаю, что идея на данный момент заключается в том, что если вы хотите иметь пользовательские типы с конечным временем жизни (например, уничтожаться при наличии области, в которой они созданы), вы должны использовать структуры. - person Jonathan M Davis; 07.07.2010
comment
@Jonathan Указатели не обязательно небезопасны. При условии, что вы берете их только в память кучи, не приводите их к несовместимым типам и не выполняете с ними непроверенные арифметические действия, они совершенно безопасны. Плохие вещи случаются только тогда, когда вы делаете глупые вещи, такие как экранирование памяти стека или деление указателя на свой рост в фарлонгах. Что касается поэтапного отказа от масштаба, это чертовски глупое решение; Я просто оставлю это на этом. - person DK.; 08.07.2010
comment
@DK Ну, теоретически, SafeD разрешает безопасное использование указателей и запрещает все остальное, поэтому, если вы придерживаетесь SafeD, все должно быть хорошо и довольно ясно. Например, безопасным случаем будет получение указателя из in с помощью ассоциативных массивов. Тем не менее, D разработан таким образом, что указатели не нужны так сильно, как в C или C++, и если они вам не нужны специально для того, что вы делаете, лучше их избегать. В частности, классы уже являются ссылочными типами, поэтому вообще не имеет смысла использовать с ними указатели. - person Jonathan M Davis; 08.07.2010

Я не очень хорошо читаю ваш код, так как я парень VB, но похоже, что вы инициируете объект, не имеющий значения.

Вы создаете объект с именем obj. Вы вызываете obj.x, а затем возвращаете «0» (ноль).

что именно ты делаешь? Я почти уверен, что obj должен быть НОВЫМ, и вам нужно возвращать что-то отличное от физического "0"

person Chase Florell    schedule 07.07.2010
comment
0 указывает на успех. Это вещь UNIX. - person DK.; 07.07.2010
comment
Все переменные в D автоматически инициализируются со значением по умолчанию, если вы его не укажете. В случае ссылок на объекты это значение равно нулю, поэтому он жалуется, что он пытается уважать нулевую ссылку. - person Jonathan M Davis; 07.07.2010
comment
так что главное остается в силе (забыв про ноль), его нужно было инициализировать как NEW. - person Chase Florell; 08.07.2010
comment
Да. Главное, безусловно, верно. Проблема в том, что переменная была инициализирована нулевым значением, а не присвоением ей фактического объекта (в данном случае, предположительно, с new). Просто в D это не будет неинициализированным значением. Скорее это значение, инициализированное по умолчанию. Итак, вы получаете null вместо мусора. Это все еще ошибка, но она четко определена и будет полностью детерминирована независимо от вашей платформы или реализации компилятора. - person Jonathan M Davis; 08.07.2010