2010-02-10 3 views
33

Существует несколько ситуаций, которые стандарт C++ присваивает как неопределенное поведение. Например, если я выделяю new[], попробуйте освободить его с delete (не delete[]), это неопределенное поведение - anything can happen - это может сработать, это может привести к непредвиденным сбоям, это может привести к некорректному повреждению и установке заданной проблемы.Как объяснить неопределенное поведение новичков-новичков?

Это так проблематично, чтобы объяснить это все может случиться часть новичкам. Они начинают «доказывать», что «это работает» (потому что он действительно работает на реализации C++, который они используют) и спрашивает «что может быть неправильно с этим»? Какое краткое объяснение я могу дать, что побудило бы их просто не писать такой код?

+3

Пощечина на руке? – villintehaspam

+5

Точно так же вы все объясняете: «Покажи, не говори». –

+1

Undefined не означает случайный, это означает, что реализация зависит. Код, который использует неопределенное поведение, не переносится, но он не будет вести себя иначе в альтернативные пятницы. (Несмотря на то, что вы, кажется, думаете). Как говорит Митч, если вы можете _show_ их, что код сломается, тогда сделайте это. Если вы не можете, то, возможно, вам стоит подумать, что вы не понимаете язык так же хорошо, как думаете. –

ответ

17

«Поздравляем, вы определили поведение, которое компилятор имеет для этой операции. Я буду ждать отчет о поведении, что другие 200 компиляторы, которые существуют в мире выставку, чтобы быть на моем столе на 10 AM завтра. Не разочаруйте меня, ваше будущее выглядит многообещающим! "

+17

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

3

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

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

+1

Yikes! Слишком много неопределенного поведения просто происходит для работы независимо от того, что они могут захотеть сделать (они скручиваются с кодом до тех пор, пока «он не будет работать на моей машине») - пока они не переместились в другое место и инструменты не будут обновлены. Вдруг плохие аспекты неопределенного поведения взорвутся перед лицом того, что все еще держится вокруг содержания вещей. –

+2

@Michael: Я все еще считаю, что «Developer Art» имеет хорошую точку зрения. Нет причин волноваться при обсуждении неопределенного поведения - это достаточно плохо, чтобы не поощрять по существу дела. Важно объяснить спокойно и понятно, почему это плохо. Цель состоит в том, чтобы препятствовать поведению, а не человеку. – JXG

+0

@Michael: Хорошо, если это был новичок в профессиональной среде, отправляя код, который, как я думал, мог взорваться в будущем, тогда он не прошел бы проверку кода. Если они продолжат подавать код, который, как они знают, не будут проходить проверку, потому что они считают, что знают лучше, чем их босс, как писать C++, это проблема для нежного завершения дисциплинарной процедуры. Если они на самом деле студент и не пишут код, который должен поддерживаться в будущем, то поручать им переносить свой дерьмовый код в компилятор, на котором он ломается, может быть достаточно, чтобы проиллюстрировать суть сделки с их собственными последствиями. –

31

Две возможности прийти на ум:

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

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

+4

Трудность с решением 2 заключается в том, что вы можете обнаружить, что ни один из доступных компиляторов фактически не срабатывает эффектно, но поведение все еще не определено и, следовательно, от этого не может зависеть. Слишком много кода написано с помощью «Я не могу найти где-то, что он ломается», и, хотя это может произойти в настоящее время, что-то может измениться (платформа, компилятор, ...), которые заставят его сломаться в будущем - и нет ошибка в системе, потому что поведение не определено (так что все правильно). Также найдите «носовые демоны» в группе новостей comp.std.c. –

+0

@ Джонатан - см. Мой ответ! – JXG

3

Спокойно переопределить новый, новый [], удаление и удаление [] и посмотреть, как долго он принимает его заметить;)

В противном случае ... просто скажите ему, что он неправ, и указать его к спецификации C++ , О да .. и в следующий раз будьте более осторожны при использовании людей, чтобы убедиться, что вы избегаете отверстий!

0

Включите malloc_debug и delete массив объектов с деструкторами. free Ошибка указателя внутри блока. Позвоните им всем и продемонстрируйте это.

Вам нужно будет подумать о других примерах, чтобы создать свой авторитет, пока они не поймут, что они новички, и о C++ многое знать.

0

Расскажите им о стандартах и ​​о том, как инструменты разработаны в соответствии со стандартами. Все, что вне стандарта может работать или не работать, это UB.

44

Неопределенные средства явно ненадежны. Программное обеспечение должно быть надежным. Вам не нужно больше говорить.

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

+6

+1 для воображения, иногда картинка стоит тысячи слов. –

1

Можно было бы ...

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

1

Просто покажите им Valgrind.

3

Мне нравится эта цитата:

Неопределенное поведение: это может повредить файлы, отформатировать диск или отправить почту ненависти к вашего босса.

Я не знаю, кому это приписать (возможно, это от Effective C++)?

+1

, но если их аргумент «смотреть, я только что скомпилировал и запустил программу, и это сработало», почему ваша цитата изменит их мнение? – jalf

+0

@jalf - вам просто нужно заменить «ваш» на «наш клиент» в цитате – Manuel

+0

Но опять же они просто * показали *, что это сработало. Кого волнует какая-то пыльная старая цитата? Почему им не следует доверять, что если это сработает, когда они запускают программу, всегда будет работать? – jalf

12

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

+0

+1 хе-хе, иногда вам просто нужно вытащить звание :) – Paolo

3

John Woods:

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

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

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

1

откомпилировать и запустить эту программу:

#include <iostream> 

class A { 
    public: 
      A() { std::cout << "hi" << std::endl; } 
      ~A() { std::cout << "bye" << std::endl; } 
}; 

int main() { 
    A* a1 = new A[10]; 
    delete a1; 

    A* a2 = new A[10]; 
    delete[] a2; 
} 

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

О единичном удалении по массивам POD. Направьте их на C++ FAQ или попросите их запустить свой код через cppcheck.

2

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

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

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

13

Просто укажите из стандарта. Если они не могут принять это, они не программисты на С ++. Христиане отрицают Библию? ;-)

1,9 Выполнение программы

  1. семантические описания в настоящем стандарте определить параметризированный недетерминированную абстрактную машину. [...]

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

  3. Некоторые другие аспекты и операции абстрактной машины описаны в этом Международном стандарте как неуказанный (например, порядок оценки аргументов функции). По возможности этот международный стандарт определяет набор допустимых видов поведения. Они определяют недетерминированные аспекты абстрактной машины. [...]

  4. Некоторые другие операции описаны в настоящем международном стандарте как undefined (например, эффект разыменования нулевого указателя). [Примечание: этот международный стандарт не предъявляет требований к поведению программ, которые содержат неопределенное поведение. -end note]

Вы не можете получить более четкое представление.

+10

* «Христиане откажут в Библии?» * - Хе-хе, вы может быть удивлен ... –

0

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

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

И действительно, почему не? Они должны предоставлять обоснованный аргумент для использования неопределенного поведения, а не наоборот. Какая причина заключается в использовании delete вместо delete[], кроме лени? (Хорошо, есть std::auto_ptr. Но если вы используете std::auto_ptr с new[] -allocated массив, вы, вероятно, следует с помощью std::vector в любом случае.)

1

Одна точка еще не упоминается о неопределенном поведении является то, что если выполнять некоторые операции будет приводит к неопределенному поведению, совместимая со стандартами реализация может быть законно, возможно, в попытке быть «полезной» или повысить эффективность, генерировать код, который потерпел бы неудачу, если бы такая операция была предпринята. Например, можно представить многопроцессорную архитектуру, в которой может быть заблокирована любая ячейка памяти, и попытка получить доступ к заблокированному местоположению (за исключением того, чтобы разблокировать его) будет останавливаться до тех пор, пока указанное местоположение не будет разблокировано.Если блокировка и разблокировка были очень дешевыми (правдоподобными, если они реализованы на аппаратных средствах), такая архитектура может быть полезна в некоторых сценариях с несколькими потоками, поскольку реализация x++ в виде (атомарно считывается и блокируется x; добавляет значение для чтения, атомарно разблокируется) и написать x) будет гарантировать, что если два потока одновременно выполняли x++, результатом было бы добавить два к x. Предоставляемые программы записываются во избежание неопределенного поведения, такая архитектура может облегчить разработку надежного многопоточного кода, не требуя больших неуклюжих барьеров памяти. К сожалению, заявление, подобное *x++ = *y++;, может привести к взаимоблокировке, если x и y были обе ссылки на одно и то же место хранения, а компилятор попытался конвейеру выполнить код как t1 = read-and-lock x; t2 = read-and-lock y; read t3=*t1; write *t2=t3; t1++; t2++; unlock-and-write x=t1; write-and-unlock y=t2;. Хотя компилятор мог избежать тупиковой ситуации, воздерживаясь от чередования различных операций, это может помешать эффективности.

3

Превратите человека в указатель. Скажите им, что они являются указателями на человека класса, и вы вызываете функцию «RemoveCoat». Когда они указывают на человека и говорят «RemoveCoat», все в порядке. Если у человека нет пальто, не беспокойтесь - мы проверяем это, все, что делает RemoveCoat, - это удалить верхний слой одежды (с проверкой на благочестие).

Теперь, что происходит, если они указывают где-то случайным, и говорят, что RemoveCoat - если они указывают на стену, тогда краска может отслаиваться, если они указывают на дерево, которое может сойти с коры, собаки могут побриться, USS Enterprise может снизить свои щиты в критический момент и т. д.!

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

+0

+1: Мне нравится аналогия – Atmocreations

Смежные вопросы