Почему конструктор C ++ знает значения переменных-членов, которые еще не назначены? [Дубликат]

Попробуйте это, это должно быть работа, иначе вам нужно распечатать ошибку, чтобы указать вашу проблему

$username = $_POST['username'];
$password = $_POST['password'];

$sql = "SELECT * from Users WHERE UserName LIKE '$username'";
$result = mysql_query($sql,$con);

while($row = mysql_fetch_array($result))
{
    echo $row['FirstName'];
}
89
задан Kyle Strand 22 December 2015 в 21:02
поделиться

8 ответов

Да, это позволяет что-то случиться. В примечании приводятся только примеры. Определение довольно ясно:

Неопределенное поведение: поведение, для которого настоящий международный стандарт не предъявляет требований.

74
ответ дан Mehrdad 28 August 2018 в 17:25
поделиться

Во-первых, важно отметить, что не только поведение пользовательской программы не определено, но и поведение компилятора не определено. Аналогично, UB не встречается во время выполнения, это свойство исходного кода.

Чтобы писатель-компилятор «поведение не определено» означает «вам не нужно учитывать эту ситуацию», , или даже «вы не можете предположить, что исходный код никогда не произведет такую ​​ситуацию». Компилятор может делать что угодно, преднамеренно или непреднамеренно, когда представлен UB, и по-прежнему является стандартным, поэтому да, если вы предоставили доступ к носу ...

Тогда не всегда возможно знать если программа имеет UB или нет. Пример:

int * ptr = calculateAddress();
int i = *ptr;

Зная, может ли это быть UB или нет, потребуется знание всех возможных значений, возвращаемых calculateAddress(), что невозможно в общем случае (см. « Проблема с остановкой "). У компилятора есть два варианта:

  • Предположим, что у ptr всегда будет действительный адрес
  • вставить проверки времени выполнения, чтобы гарантировать определенное поведение

Первый вариант создает быстрые программы и ставит бремя избежать нежелательных эффектов на программиста, тогда как второй вариант обеспечивает более безопасный, но более медленный код.

Стандарты C и C ++ оставляют этот выбор открытым, и большинство компиляторы выбирают первый, в то время как Java, например, задает второй.


Почему поведение не определено реализацией, но неопределено?

Реализация -определенные средства ( N4296 , 1.9§2):

Некоторые аспекты и операции абстрактной машины описаны в этом Международном стандарте в качестве реализации (например, sizeof (int)). Они составляют параметры абстрактной машины. Каждая реализация должна включать документацию, описывающую ее характеристики и поведение в этих отношениях. Такая документация должна определять экземпляр абстрактной машины, которая соответствует этой реализации (упоминается как «соответствующий экземпляр» ниже).

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

Запись на случайный ненулевой Недопустимый указатель - одна из самых непредсказуемых вещей, которые вы можете сделать в программе, поэтому для этого потребуется также сократить время выполнения. До того, как у нас были MMU, вы могли бы уничтожить аппаратное обеспечение , написав неверный адрес, который приходит очень рядом с носовыми демонами; -)

5
ответ дан alain 28 August 2018 в 17:25
поделиться

Неопределенное поведение позволяет компиляторам генерировать более быстрый код в некоторых случаях. Рассмотрим две разные архитектуры процессоров, которые ADD по-разному: процессор A по сути отбрасывает бит переноса при переполнении, в то время как процессор B генерирует ошибку. (Разумеется, процессор C по своей сути генерирует Nasal Demons - это самый простой способ разрядить этот дополнительный бит энергии в наноблоте с сопливым питанием ...)

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

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

Кроме того, когда программист точно знает, что неопределенное поведение действительно вызовет в их заданной среде, они могут использовать эти знания для получения дополнительной производительности.

Если вы хотите, чтобы ваш код вел себя точно так же на всех платформах, вам нужно убедиться, что «неопределенное поведение» никогда не происходит, однако это может быть не ваша цель.

Изменить: (В ответ на редактирование OP) Реализация Определенное поведение потребует последовательной генерации носовых демонов. Неопределенное поведение позволяет спорадической генерации носовых демонов.

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

1
ответ дан Allen 28 August 2018 в 17:25
поделиться

Nitpicking: вы не указали стандарт.

Это источники, используемые для создания черновиков стандарта C ++. Эти источники не следует рассматривать как публикацию ИСО, а также документы, созданные из них, если они официально не приняты рабочей группой C ++ (ISO / IEC JTC1 / SC22 / WG21).

Интерпретация: примечания не нормативный в соответствии с Директивами ISO / IEC, часть 2.

Примечания и примеры, включенные в текст документа, должны использоваться только для предоставления дополнительной информации, предназначенной для оказания помощи понимание или использование документа. Они не должны содержать требования («должны», см. 3.3.1 и таблицу H.1) или любую информацию, считающуюся необходимой для использования документа, например. инструкции (обязательно, см. таблицу H.1), рекомендации («следует», см. 3.3.2 и таблицу H.2) или разрешение («может», см. таблицу H.3). Заметки могут быть написаны как утверждение факта.

Акцент мой. Это само по себе исключает «полный список вариантов». Однако приведение примеров относится к «дополнительной информации, предназначенной для содействия пониманию документа».

Имейте в виду, что «носовой демон» не должен восприниматься буквально, так же как использование воздушного шара, чтобы объяснить, как вселенная расширяет работу, не имеет правды в физической реальности. Это можно проиллюстрировать, что безрассудно обсуждать, что должно делать «неопределенное поведение», когда разрешено что-либо делать. Да, это означает, что в космическом пространстве нет реальной резиновой ленты.

21
ответ дан Jonathan Leffler 28 August 2018 в 17:25
поделиться

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

«Игнорирование ситуации - Да, стандарт идет на то, что это будет иметь «непредсказуемые результаты», но это не то же самое, что и код компилятора, который, как я полагаю, был бы необходимым условием для носовых демонов).

Ситуация в которые можно было бы разумно ожидать от разумного компилятора, без компилятора, вставляющего ЛЮБОЙ код, были бы следующими:

if(!spawn_of_satan)
    printf("Random debug value: %i\n", *x); // oops, null pointer deference
    nasal_angels();
else
    nasal_demons();

Компилятор, если он может доказать, что это * x является null pointer dereference, совершенно прав, как часть некоторой оптимизации, сказать «ОК, поэтому я вижу, что они разыменовали нулевой указатель в этой ветке if. Поэтому, как часть этой ветви, мне разрешено делать что я могу оптимизировать: «

if(!spawn_of_satan)
    nasal_demons();
else
    nasal_demons();

« И оттуда я могу оптимизировать это: «

nasal_demons();

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

EDIT: Один пример, который только что пришел из глубины моей памяти о таком случае, когда это полезно для оптимизации, вы часто проверяете указатель на наличие NULL (возможно, в встроенных вспомогательных функциях), даже после того, как он уже разыменовал его и не изменил его. Оптимизирующий компилятор может видеть, что вы разыменовали его, и поэтому оптимизируйте все проверки «is NULL», поскольку, если вы разыменовали его и он имеет значение NULL, что-либо разрешено, в том числе просто не выполняется «NULL», чеки. Я считаю, что подобные аргументы применимы и к другому неопределенному поведению.

6
ответ дан Muzer 28 August 2018 в 17:25
поделиться

Определение неопределенного поведения в каждом стандарте C и C ++ заключается в том, что стандарт не налагает никаких требований на то, что происходит.

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

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

10
ответ дан Peter 28 August 2018 в 17:25
поделиться

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

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

Итак, предположим, что ваш код содержит на самом деле надуманный пример, подобный приведенному ниже:

int bar = 0;
int foo = (undefined behavior of some kind);
if (foo) {
   f();
   bar = 1;
}
if (!foo) {
   g();
   bar = 1;
}
assert(1 == bar);

Компилятор может предположить, что! Foo является истинным в первом блоке, а foo - true во втором и, таким образом, оптимизирует весь фрагмент кода. Теперь логически либо foo, либо! Foo должно быть истинным, и поэтому, глядя на код, вы разумно сможете предположить, что бар должен равняться 1 после запуска кода. Но поскольку компилятор оптимизирован таким образом, бару никогда не присваивается значение 1. И теперь это утверждение становится ложным, и программа завершается, что является поведением, которое не произошло бы, если бы foo не полагался на неопределенное поведение.

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

3
ответ дан Ray 28 August 2018 в 17:25
поделиться

Неопределенное поведение - это просто результат ситуации, которую авторы спецификации не предвидели.

Возьмите идею светофора. Красный означает остановку, желтый означает готовность к красному, а зеленый означает «идти». В этом примере люди, управляющие автомобилями, - это реализация спецификации.

Что произойдет, если включены зеленый и красный? Ты останавливаешься, а потом уходишь? Вы ждете, пока красный не выключится, и он просто зеленый? Это случай, который спецификация не описала, и, как результат, все, что делают драйверы, - это неопределенное поведение. Некоторые люди сделают одно, другое. Поскольку нет гарантии того, что произойдет, вы хотите избежать этой ситуации. То же самое касается кода.

2
ответ дан Waters 28 August 2018 в 17:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: