Код с неопределенным поведением в C # - PullRequest
46 голосов
/ 07 декабря 2009

В C ++ существует множество способов написания кода, который компилируется, но дает неопределенное поведение (Википедия) . Есть ли что-то подобное в C #? Можем ли мы написать код на C #, который компилируется, но имеет неопределенное поведение?

Ответы [ 7 ]

37 голосов
/ 07 декабря 2009

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

Угловой случай целочисленного деления имеет поведение, определяемое реализацией.

Создание исключения и его никогда не вызывает поведение, определяемое реализацией - завершите процесс, запустите отладчик и т. Д.

В C # существует ряд других ситуаций, когда мы вынуждены генерировать код с поведением, определяемым реализацией. Например, эта ситуация:

http://blogs.msdn.com/ericlippert/archive/2006/04/06/odious-ambiguous-overloads-part-two.aspx

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

28 голосов
/ 03 октября 2014

Да! Есть даже в безопасном контексте! (Ну, его реализация определена как неопределенная, по крайней мере)

Вот одна из работ Марека Сафара и В.С.адова в Рослине . Существует несоответствие между C # и CLI в отношении bool

C # считает, что существует только один вид true и один вид false.

CLI считает, что false - это байт, содержащий 0, а все остальные значения true.

Это несоответствие означает, что мы можем заставить C # сделать некоторые (незначительно) интересные вещи вещь:

//non-standard bool
//We're setting a bool's value to a byte value of 5.
var a = new bool[1];
Buffer.SetByte(a, 0, 5);

//non-standard bool
//We're setting a bool's value to a byte value of 10.
var b = new bool[1];
Buffer.SetByte(b, 0, 10);

//Both are true.
Console.WriteLine(a[0]);
Console.WriteLine(b[0]);

//But they are not the same true.
Console.WriteLine(a[0] == b[0]);

Вышеуказанные выходы:

true

true

false

Интересно, что отладчик не согласен (должен по-другому оценивать истину?)

enter image description here

В любом случае, команда C # пришла к выводу (выделение добавлено):

т.е. язык останется совершенно безразличным к нестандартным bools. Конкретная реализация (как в MS C # на CIL) будет признавать существование нестандартных bools и определять их поведение как undefined

13 голосов
/ 07 декабря 2009

Глядя на вики, ситуации, в которых происходит неопределенное поведение, либо недопустимы, либо выдают исключение в C #.

Тем не менее, в небезопасном коде возможно неопределенное поведение, так как это позволяет вам использовать указатели и т. Д.

Редактировать: Похоже, я прав: http://msdn.microsoft.com/en-us/library/aa664771%28VS.71%29.aspx

Имеет пример неопределенного поведения в c #

11 голосов
/ 08 декабря 2009

Согласно документу ECMA-334 (стр. 473):

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

Это продвигает «определение реализации» в худшем случае, см. Ответ Эрика Липперта

1 голос
/ 22 июня 2015

Многие и подпрограммы имеют требования, которые можно обобщить как:

  1. При наличии достоверных данных выведите действительный вывод.

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

Одна из основных целей разработки языков Java и .NET заключается в том, что, если в коде не используются некоторые из них, помеченные как «небезопасные», как правило, не требуется никаких особых усилий для удовлетворения второго ограничения, приведенного выше [хотя некоторые виды поведения связаны с мусором сбор и Finalize могут быть немного странными с точки зрения времени / причинности, которые могут быть описаны как исключения из обычных правил причинности, а не как их полный отзыв]. Эта ситуация очень отличается от ситуации в C, где многие виды ошибок, зависящих от данных (например, целочисленное переполнение), могут привести к тому, что компиляторы будут вести себя произвольным образом, включая принятие любых допущений, необходимых для избежания переполнения. Действительно ужасные виды неопределенного поведения, которые поощряются в гиперсовременной философии C, не существуют в C # или других языках .NET за пределами «небезопасных» блоков.

0 голосов
/ 07 декабря 2009

Вообще я бы сказал нет.

Использовать автоматическую переменную до ее инициализации.

Все переменные должны быть инициализированы. Если не исключение происходит.

Деление на ноль

Исключение выдается.

Индексирование массива за пределами

Исключение брошено

Как указано Aequitarum Custos, вы можете использовать небезопасный код. Опять же, это на самом деле не C #, вы явно отказываетесь от среды C #.

0 голосов
/ 07 декабря 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...