In C++ there are a lot of ways that you can write code that compiles, but yields undefined behavior (Wikipedia). Is there something similar in C#? Can we write code in C# that compiles, but has undefined behavior?
7 Answers
As others have mentioned, pretty much anything in the "unsafe" block can yield implementation-defined behaviour; abuse of unsafe blocks allows you to change the bytes of code that make up the runtime itself, and therefore all bets are off.
The division int.MinValue/-1
has an implementation-defined behaviour.
Throwing an exception and never catching it causes implementation-defined behaviour -- terminate the process, start a debugger, and so on.
There are a number of other situations in C# where we are forced to emit code which has implementation-determined behaviour. For example, this situation:
https://learn.microsoft.com/en-us/archive/blogs/ericlippert/odious-ambiguous-overloads-part-two
However, the situations in which a safe, well-behaved C# program has implementation-defined behaviour should be quite rare.

- 3,514
- 2
- 21
- 44

- 647,829
- 179
- 1,238
- 2,067
-
Ouch, that overload issue is really weird. And I thought DivisionByZeroException was the expected behavior on `1/0`. Anyway, I'll +1 this tomorrow... – R. Martinho Fernandes Dec 07 '09 at 16:14
-
1Who said anything about division by zero? – Eric Lippert Dec 07 '09 at 16:19
-
5@Eric: I thought the corner case you mentioned was the usual 1/0. I searched around and I found it's actually `int.MinValue/-1`. – R. Martinho Fernandes Dec 07 '09 at 16:41
-
2Does anyone know or can anyone speculate why `int.MinValue/-1` isn't or couldn't be defined in the language specification? – Nick Strupat Feb 03 '15 at 03:13
-
@NickStrupat: This is a question and answer site; if you have a question, post a question! – Eric Lippert Feb 03 '15 at 14:58
-
2@NickStrupat: See [explanation by Hans Passant](http://stackoverflow.com/a/26594915/18192) – Brian Feb 04 '15 at 14:03
-
1Are you aware, that implementation defined and undefined behavior are two totally different things in c++? – MikeMB Jan 19 '16 at 08:50
-
7@MikeMB: I am. It's a subtle distinction that I usually don't bother making in the context of C# unless I need to be extraordinarily precise. The fact that the C++ specification authors felt the need to make a *taxonomy* of ways in which the language can trip you up without telling you is not something I consider to be a strength of the language. – Eric Lippert Jan 19 '16 at 15:03
-
1The reason why I'm asking is, because - while answering another questions - I was wondering whether it is possible to cause UB by non-unsafe C#-code-blocks. In c++ it makes actually an enormous difference whether something is implementation defined or undefined behavior. The former just results in non-portable code, the latter results in - by definition - completely unpredictable behavior of your program. But from your answer, it isn't obvious, whether the other examples are IB or genuinely (c++ like) UB. And yes, all the UB clauses in the standard are definitively not my favorite part of c++. – MikeMB Jan 19 '16 at 23:50
-
@MikeMB: Ah, that is a different kettle of fish altogether. Yes, there are ways you can mess stuff up without having any marked-as-unsafe code in your program, but this comment is maybe not a great place to enumerate them. \ – Eric Lippert Jan 20 '16 at 01:03
-
NP. I think the other answers (especially by Henk and Brett) cover my particular question. – MikeMB Jan 20 '16 at 07:45
Yes! There is, even in a safe context! (Well, it's implementation defined to be undefined, at least)
Here's one from Marek Safar and VSadov in the Roslyn issues.There is a mismatch between C# and the CLI in regards to bool
.
C# believes that there is only one kind of true
, and one kind of false
.
CLI believes that false
is a byte containing 0, and all other values are true
.
This discrepancy means we can coerce C# to do some a (marginally) interesting things thing:
//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]);
The above outputs:
true
true
false
Interestingly, the debugger disagrees (must evaluate truth differently?)
Anyways, the conclusion the C# team appears to have come to is (emphasis added):
I.E. the language will stay entirely unconcerned about nonstandard bools. The particular implementation (as in MS C# on CIL) will acknowledge the existence of nonstandard bools and specify their behavior as undefined

- 9,066
- 4
- 52
- 80
Looking at the Wikipedia article on undefined behaviour, the situations in which undefined behavior happens are either not allowed or throw an exception in C#.
However in Unsafe code, undefined behavior I believe is possible, as that allows you to use pointers etc.
Edit: It looks like I'm right: http://msdn.microsoft.com/en-us/library/aa664771%28VS.71%29.aspx
Has an example of undefined behavior in c#

- 354
- 6
- 13

- 5,297
- 5
- 32
- 62
-
6
-
1@Jeff Yates: The "undefined behavior" link up in the question goes to Wikipedia. – Powerlord Dec 07 '09 at 15:24
-
@Jeff Yates: Yeah, I was looking to his wikipedia link to determine what situations cause undefined behaviors. – Brett Allen Dec 07 '09 at 15:27
-
1
According to the ECMA-334 document (p. 473):
A program that does not contain any occurrences of the unsafe modifier cannot exhibit any undefined behavior.
That promotes 'implementation-defined' to the worst case, see Eric Lippert's answer.

- 263,252
- 30
- 330
- 514
-
Unspecified, rather than Implementation-Defined, at least as the term is used in the C spec. If the spec regards an implementation as Implementation-Defined, then conforming implementations are required to provide sufficient documentation to let a programmer know exactly how it will behave. An implementation could legitimately specify that `(signed char)128` would yield -126 during the first half of each phase of the moon, and -127 during the second half, but only if the implementation actually ascertains the phase of the Moon. Implementations cannot simply say "yields arbitrary value". – supercat Jun 29 '15 at 22:00
Many and subprograms have requirements that can be summarized as:
When given valid data, produce valid output.
Refrain from launching nuclear missiles or negating the laws of time and causality, even when given invalid input.
One of the major design goals of Java and .NET languages is that unless code makes use of certain which are marked as "unsafe", no particular effort is generally required to meet the second constraint above [though some behaviors related to garbage collection and Finalize
can be a little weird from the time/causality standpoint, those can be described as exceptions to normal rules of causality, rather than a total revocation of them]. That situation is very different from the situation in C, where many kinds of data-dependent errors (e.g. integer overflow) may result in compilers behaving in arbitrary fashion including making whatever assumptions would be necessary to avoid overflow. The truly horrible kinds of Undefined Behavior which are encouraged in hypermodern C philosophy do not exist in C# or other .NET languages outside of "unsafe" blocks.

- 77,689
- 9
- 166
- 211
Not really in the exactly Wiki sense but I suppose the most obvious example that comes to my mind is simply writing some threaded code, but then it's like that in any language.

- 7,667
- 4
- 31
- 44
-
3That's just nondeterministic, not undefined. You're still given a guarantee of exactly what each thread will be doing. You just don't know the exact order in which things happen, and so you might get some surprising results. – jalf Dec 07 '09 at 15:39
-
2@mfloryan: unfortunately, whenever you spawn a new thread in C# you can't expect a game of NetHack to be started. Ah, good days when you could play it by running gcc... – R. Martinho Fernandes Dec 07 '09 at 15:45
In general I would say no.
Use Automatic variable before it’s initialized.
All variables must be initialized. If not an exception occurs.
Division by zero
Exception is thrown.
Indexing an array out of bounds
Exception is thrown
As Aequitarum Custos pointed out you can use unsafe code. Then again this isn't really C#, you are explicitly opting out of the C# environment.

- 16,287
- 11
- 58
- 101
-
3Unsafe code *is* C#. What you're opting out of is the managed code guarantees. – R. Martinho Fernandes Dec 07 '09 at 15:28
-
This is *not* C# unsafe { int* px1; int* px2 = &i; F(out px1, ref px2); Console.WriteLine("*px1 = {0}, *px2 = {1}", *px1, *px2); // undefined behavior } Yes it's written with in C#. – Chuck Conway Dec 07 '09 at 15:49
-
7Sure, that's perfectly legal C#. An implementation of C# that implements the optional "unsafe" subset is still an implementation of C#. – Eric Lippert Dec 07 '09 at 16:08