Подтвердить что ты не робот

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

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

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

Ответ 1

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

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

Вопрос в дефекте искал исключения для memcpy и fwrite, если это действительно так:

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

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

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

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

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

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

Стоит отметить, что это отличается от С++, где чтение неопределенного значения из узкого unsigned char не является undefined поведение и отчет о дефектах 240 отмечает эту разницу:

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

Ответ 2

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

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

6.3.2.1p2

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

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

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

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

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

Ответ 3

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

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