代码之家  ›  专栏  ›  技术社区  ›  luvieere

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

  •  44
  • luvieere  · 技术社区  · 15 年前

    在C++中,有很多方法可以编写编译的代码,但是 undefined behavior (Wikipedia) .C中有类似的东西吗?我们能用C编写编译但有未定义行为的代码吗?

    7 回复  |  直到 7 年前
        1
  •  36
  •   Eric Lippert    15 年前

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

    整数除法的角情况有一个实现定义的行为。

    抛出异常而从不捕获它会导致实现定义的行为——终止进程、启动调试器等等。

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

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

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

        2
  •  27
  •   JoshVarty Dean Poulin    7 年前

    对!即使在一个安全的环境中也存在!(好吧,它的实现至少定义为未定义)

    这是Marek Safar和Vsadov在 Roslyn issues 。C和CLI之间在以下方面不匹配: bool .

    C认为只有一种 true 和一种 false .

    cli认为 是包含0的字节,所有其他值都是 .

    这种差异意味着我们可以强迫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]);
    

    以上输出:

    有趣的是,调试器不同意(必须以不同的方式评估真相?)

    enter image description here

    不管怎样,C小组得出的结论是(重点补充):

    也就是说,语言将完全不关心非标准的bools。特定的实现(如在CIL上的MS C中)将确认存在非标准的bool,并将其行为指定为 未定义

        3
  •  13
  •   Brett Allen    15 年前

    查看wiki,不允许出现未定义行为的情况,或者在c中引发异常。

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

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

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

        4
  •  11
  •   Henk Holterman    15 年前

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

    不包含任何 不安全修饰符的出现 不能显示任何未定义的 行为。

    这将“定义的实现”提升到最坏的情况,请参阅EricLippert的答案。

        5
  •  1
  •   supercat    9 年前

    许多子程序和子程序都有如下要求:

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

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

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

        6
  •  0
  •   Chuck Conway    15 年前

    一般来说,我会说不。

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

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

    除以零

    引发异常。

    索引超出界限的数组

    引发异常

    正如aequitarum custos指出的,您可以使用不安全的代码。再次强调,这不是真正的C,您明确地选择退出C环境。

        7
  •  -1
  •   mfloryan    15 年前

    并不是真正意义上的wiki,但我认为我想到的最明显的例子就是编写一些线程代码,但在任何语言中都是这样。