C#中具有未定义行为的代码

时间:2009-12-07 15:15:23

标签: c# c++ undefined-behavior

在C ++中,有很多方法可以编写编译的代码,但会产生undefined behavior (Wikipedia)。 C#中有类似的东西吗?我们可以用编译的C#编写代码,但是有不确定的行为吗?

7 个答案:

答案 0 :(得分:37)

正如其他人所提到的,“不安全”块中的任何内容都可以产生实现定义的行为;滥用不安全的块允许您更改构成运行时本身的代码字节,因此所有的赌注都会关闭。

整数除法的极端情况具有实现定义的行为。

抛出异常并且永远不会捕获它会导致实现定义的行为 - 终止进程,启动调试器等等。

在C#中还有许多其他情况,我们被迫发出具有实现确定行为的代码。例如,这种情况:

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

但是,安全,行为良好的C#程序具有实现定义行为的情况应该非常少见。

答案 1 :(得分:27)

是的!即使在安全的背景下,也有! (好吧,它的实现定义为未定义,至少)

这是来自Roslyn issues的Marek Safar和VSadov的一个。关于bool,C#和CLI之间存在不匹配。

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#团队似乎已经得出结论(重点补充):

  

即。语言将完全不关心非标准的bool。特定实现(如在CIL上的MS C#中)将确认非标准bool的存在并将其行为指定为 undefined

答案 2 :(得分:13)

查看Wiki,不允许发生未定义行为的情况或在C#中抛出异常。

但是在不安全的代码中,我认为未定义的行为是可能的,因为它允许你使用指针等。

编辑:看起来我是对的:http://msdn.microsoft.com/en-us/library/aa664771%28VS.71%29.aspx

在c#

中有一个未定义行为的示例

答案 3 :(得分:11)

根据ECMA-334文件(第473页):

  

不包含任何内容的程序   出现不安全修饰符   不能展示任何未定义的   行为。

这促使'实施定义'到最坏的情况,请参阅Eric Lippert的回答。

答案 4 :(得分:1)

许多和子程序的要求可以概括为:

  1. 给定有效数据时,生成有效输出。

  2. 即使给予无效输入,也不要发射核导弹或否定时间和因果律。

  3. Java和.NET语言的主要设计目标之一是,除非代码使用标记为"不安全的某些内容,否则通常不需要特别的努力来满足上面的第二个约束[虽然从时间/因果关系的角度来看,与垃圾收集和Finalize相关的一些行为可能有点奇怪,这些可以被描述为正常的因果关系规则的例外,而不是对它们的完全撤销]。这种情况与C中的情况非常不同,其中许多类型的数据相关错误(例如整数溢出)可能导致编译器以任意方式运行,包括做出必要的假设以避免溢出。在超现代C哲学中鼓励的真正可怕的未定义行为并不存在于C#或其他.NET语言之外"不安全"块。

答案 5 :(得分:0)

总的来说,我会说不。

在自动变量初始化之前使用。

必须初始化所有变量。如果没有异常发生。

除以零

抛出异常。

将数组索引越界

抛出异常

正如Aequitarum Custos指出的那样,你可以使用不安全的代码。那么这不是真正的C#,你明确地选择退出C#环境。

答案 6 :(得分:-1)

并不是真正的维基意义,但我想我脑海中最明显的例子就是编写一些线程代码,但就像任何语言一样。