гарантируют ли memset или bzero, что указатель поля в структуре будет обнулен?

Предположим, у вас есть класс Foo C++, и вы говорите:

Foo* foos = new Foo[SOME_CONSTANT];
memset(foos, 0, sizeof(Foo)*SOME_CONSTANT);
//or the bzero equivalent

и у Foo есть элемент данных Bar* barPtr. Гарантирует ли вышеуказанная операция, что barPtr будет NULL? (то есть ноль). Я столкнулся с случаем в gdb, когда это не соблюдалось для memset, и мне любопытно, почему.

Я знаю, что это, вероятно, плохая практика, но я прошу любопытства.

Я понял, что у меня есть лишний , я делал sizeof(Foo)*SOME_CONSTANT в memset...


person Palace Chan    schedule 02.11.2012    source источник
comment
Кажется, есть некоторая путаница в том, что вы спрашиваете. memset должен гарантировать, что barPtr установлен в нули, что не обязательно равно NULL. Какое значение вы увидели для barPtr?   -  person James    schedule 02.11.2012
comment
memset() установит цель на все биты-ноль. Это обычно устанавливает указатели в нуль, но язык не требует, чтобы нулевой указатель был представлен как все биты-ноль. Но я удивлен вашим случаем с gdb, где это не относится к memset; Я не знаю ни одной системы, поддерживающей gdb, где нулевые указатели не являются нулевыми битами.   -  person Keith Thompson    schedule 02.11.2012


Ответы (2)


С одной стороны, это определяется реализацией. memset или bzero заполнит значение указателя нулевым битовым шаблоном, который не гарантирует физического представления нулевого указателя на данной платформе. Даже не гарантируется создание действительного значения указателя, а это означает, что вы можете получить так называемое представление-ловушку, которое вызывает неопределенное поведение при доступе.

С другой стороны, bzero является (или раньше) частью спецификации POSIX. Если память не изменяет, POSIX требует (или, по крайней мере, раньше требовал), чтобы нулевые указатели были представлены нулевым битовым шаблоном, а это означает, что в системах POSIX он действительно установит указатель на нуль.

Но опять же, гарантия, предоставляемая POSIX, - это всего лишь пример свойства, специфичного для реализации, упомянутого в первой части моего ответа. Язык (C или C++) таких гарантий не дает.

person AnT    schedule 02.11.2012

Нет. Представление нулевого указателя не обязательно должно быть нулевым во всех битах.

См. раздел 5 и вопрос 7.31 из comp. lang.c Часто задаваемые вопросы.

person lhf    schedule 02.11.2012
comment
@ Джеймс, я думаю, что да. См. FAQ, который я добавил к своему ответу. - person lhf; 02.11.2012
comment
@aleguna, нет. См. FAQ. Запись p=0 не устанавливает все биты p в ноль, если p является указателем. - person lhf; 02.11.2012
comment
Вопросы не о NULL, он спрашивает, почему его вызов memset не обнуляет члены класса - person James; 02.11.2012
comment
@lhf, первая строка вопроса говорит класс - person James; 02.11.2012
comment
@aleguna: NULL в C можно определить как постоянный целочисленный нуль, а не просто любой ноль. т.е. такой NULL должен быть нулем времени компиляции, немедленно распознаваемым компилятором как ноль. Является ли такой нуль сам по себе полностью нулевым или совершенно не имеет значения, поскольку его представление может полностью измениться после преобразования в тип указателя. Между тем, если NULL в C определяется как (void *) 0, вы больше не можете утверждать, что все биты равны нулю. (void *) 0 может легко заменить 0xBAADFOOD физически. - person AnT; 02.11.2012