Является ли неопределенное поведение memcpy из неинициализированной переменной?

использует неинициализированную переменную в качестве src на memcpy неопределенное поведение в C?

void foo(int *to)
{
  int from;
  memcpy(to, &from, sizeof(from));
}

3 ответов


комитет C предложил ответ на отчет о дефектах 451: нестабильность неинициализированных автоматических переменных - это:

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

вопрос в дефекте искал освобождение для memcpy и fwrite, если это действительно так, говоря:

[...] Тот факт, что один хочет иметь возможность копировать неинициализированная прокладка байт в структурах помощью memcpy без неопределенному поведению есть причина что использование значения неинициализированного объекта не является неопределенным поведение. Это, по-видимому, предполагает, что fwrite структуры с неинициализированные байты заполнения не должны демонстрировать неопределенное поведение.

эта часть ответа предложения, похоже, направлена на эту озабоченность по поводу неинициализированного заполнения:

комитет также отмечает, что балластом в структуры возможно, это особая форма" шаткого " представления.

мы можем видеть форму отчет о дефектах 338: C99, похоже, исключает неопределенное значение из неинициализированного регистра это несколько отличается от прошлых ожиданий. В нем, среди прочего, говорится:--3-->

[...] Я поверьте в намерение исключить тип unsigned char из наличия ловушки представления должны были позволить использовать его для копирования (через memcpy) произвольный память, в случае, если память может содержать ловушку представления для некоторых типов.[...]

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

стоит отметить, что это отличается от C++, где значение неопределенное значение из узкого беззнаковый char это не неопределенное поведение и отчет о дефекте 240 отмечает это различие:

комитет C занимается аналогичной проблемой в своем DR338. Согласно этому анализу, они планируют принять почти противоположный подход к описанному выше, увеличив описание своей версии преобразования lvalue в rvalue. CWG не считает, что доступ к неподписанному char все еще может быть заблокирован, если он выделен в регистре, и нуждается в переоценке предлагаемой резолюции в этом свет. Смотрите также выпуск 129.


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

другие ответы имеют цитаты из стандарта C, которые не определены поведение происходит, когда значение неинициализированной переменной "используется". Что, очевидно, не применяется, если вы не используете значение. Существует еще одно упоминание в стандартном неопределенном поведении C11 при копировании / назначении неинициализированных переменных:

6.3.2.1п2

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

это также не влияет на ваш код, потому что адрес from берется при вызове memcpy

другой важной частью стандарта C11 является 6.2.6.1

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

некоторые очень старые процессоры могут иметь ловушка представление для int или программно-видимые биты четности или "отрицательный нуль" в архитектурах не-двойки-дополнения. например, процессоры x86 не имеют представлений trap для int.


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

(поскольку выделение пространства и не инициализация переменных не УБ .)