标签: undefined-behavior

您遇到的C的常见未定义/未指定行为是什么?

C语言中未指定行为的一个示例是评估函数参数的顺序.它可能是左右或左右,你只是不知道.这会影响评估方式foo(c++, c)foo(++c, c)得到评估.

还有什么其他未指明的行为可以让不知情的程序员感到惊讶?

c undefined-behavior language-lawyer unspecified-behavior

63
推荐指数
9
解决办法
1万
查看次数

在C++ 14中,C++标准是否在使用不确定值和未定义行为方面发生了变化?

正如初始化所述,需要进行左值到右值的转换?是int x = x;UB吗?C++标准在3.3.2 声明部分中有一个令人惊讶的例子,其中a int用它自己的不确定值初始化:

int x = 12;
{ int x = x; }
Run Code Online (Sandbox Code Playgroud)

这里第二个x用它自己的(不确定的)值初始化.- 结束例子 ]

Johannes对此问题的回答表明是未定义的行为,因为它需要左值到右值的转换.

在最新的C++ 14草案标准中N3936,可以在此处找到此示例已更改为:

unsigned char x = 12;
{ unsigned char x = x; }
Run Code Online (Sandbox Code Playgroud)

这里第二个x用它自己的(不确定的)值初始化.- 结束例子 ]

C++ 14中有关于不确定值和未定义行为的变化,这些变化在示例中引发了这种变化吗?

c++ undefined-behavior language-lawyer c++11 c++14

62
推荐指数
1
解决办法
3991
查看次数

假设指向同一变量的两个指针是非法的/UB,为什么 C 编译器不能优化更改 const 指针的值?

最近我偶然发现了 Rust 和 C 之间的比较,它们使用以下代码:

bool f(int* a, const int* b) {
  *a = 2;
  int ret = *b;
  *a = 3;
  return ret != 0;
}
Run Code Online (Sandbox Code Playgroud)

在 Rust(相同的代码,但使用 Rust 语法)中,它生成以下汇编代码:

    cmp      dword ptr [rsi], 0 
    mov      dword ptr [rdi], 3 
    setne al                    
    ret
Run Code Online (Sandbox Code Playgroud)

使用 gcc 时,它会产生以下结果:

   mov      DWORD PTR [rdi], 2   
   mov      eax, DWORD PTR [rsi]
   mov      DWORD PTR [rdi], 3        
   test     eax, eax                  
   setne al                           
   ret
Run Code Online (Sandbox Code Playgroud)

文本声称 C 函数不能优化第一行,因为ab可能指向相同的数字。在 Rust 中这是不允许的,因此编译器可以将其优化掉。

现在我的问题:

该函数采用一个const …

c strict-aliasing undefined-behavior rust

62
推荐指数
3
解决办法
2974
查看次数

访问绑定的未定义行为之外的全局数组?

我今天刚上课了 - 阅读C代码和输入,如果程序实际运行,所需答案就是屏幕上显示的内容.其中一个问题被声明a[4][4]为一个全局变量,并且在该程序的一个点上,它试图访问a[27][27],所以我回答了类似" 访问一个超出其边界的数组是一个未定义的行为 ",但老师说它a[27][27]的值将为0.

之后,我尝试了一些代码来检查"所有未初始化的golbal变量是否设置为0"是否为真.好吧,这似乎是真的.

所以现在我的问题是:

  • 似乎已经清除了一些额外的内存并保留了代码运行.保留多少内存?为什么编译器会保留比应该更多的内存,它的用途是什么?
  • a[27][27]0所有环境?

编辑:

在该代码中,a[4][4]唯一声明的全局变量,并且还有一些更多本地变量main().

我在DevC++中再次尝试了该代码.所有这些都是0.但在VSE中并非如此,其中大多数值都是,0但有些值具有Vyktor指出的随机值.

c undefined-behavior

60
推荐指数
7
解决办法
3235
查看次数

一个检测未定义行为的C++实现?

C++中的大量操作会导致未定义的行为,其中规范完全静音程序的行为应该是什么,并允许任何事情发生.因此,有各种各样的情况,人们有代码在调试但不是发布模式编译,或者直到看似无关的更改,或者在一台机器而不是另一台机器上工作,等等.

我的问题是是否有一个实用程序查看C++代码的执行并标记程序调用未定义行为的所有实例.虽然我们有很好的工具,比如valgrind和检查过的STL实现,但这些并不像我想的那么强 - 例如,如果你丢弃了你仍然分配的内存,那么valgrind会有误报,并且检查了STL实现不会通过基类指针捕获删除.

这个工具存在吗?或者让它躺在身边甚至是有用的?

编辑:我知道一般来说静态检查C++程序是否可能执行具有未定义行为的东西是不可判定的.但是,可以确定C++ 的特定执行是否产生了未定义的行为.实现此目的的一种方法是创建一个C++解释器,根据规范中列出的定义逐步执行代码,在每个点确定代码是否具有未定义的行为.这不会检测特定程序执行中未发生的未定义行为,但会发现任何实际在程序中显示的未定义行为.这与图灵识别如何确定TM是否接受某些输入有关,即使它通常仍然是不可判定的.

谢谢!

c++ undefined-behavior

59
推荐指数
5
解决办法
6296
查看次数

为什么这是一个未定义的行为?

我对这个问题的回答是这个函数:

inline bool divisible15(unsigned int x) 
{
    //286331153 = (2^32 - 1) / 15
    //4008636143 = (2^32) - 286331153
    return x * 4008636143 <= 286331153;
}
Run Code Online (Sandbox Code Playgroud)

它完全适用于我的机器与VS2008编译器,但在这里它根本不起作用.

有没有人有想法,为什么我在不同的编译器上得到不同的结果? unsigned溢出不是未定义的行为.

重要提示:经过一些测试后,确认它比将除法的余数除以15更快.(但不是在所有编译器上)

c c++ undefined-behavior

59
推荐指数
2
解决办法
2555
查看次数

为什么a =(a + b) - (b = a)是交换两个整数的不错选择?

我偶然发现了这个代码,用于交换两个整数而不使用临时变量或使用按位运算符.

int main(){

    int a=2,b=3;
    printf("a=%d,b=%d",a,b);
    a=(a+b)-(b=a);
    printf("\na=%d,b=%d",a,b);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

但我认为这段代码在swap语句中有未定义的行为,a = (a+b) - (b=a);因为它不包含任何序列点来确定评估的顺序.

我的问题是:这是交换两个整数的可接受的解决方案吗?

c c++ swap undefined-behavior sequence-points

58
推荐指数
9
解决办法
7681
查看次数

为什么代码会通过空指针显式调用静态方法?

我在几个旧项目中看到过这样的代码:

class Class {
    static void Method() {}
};

((Class*)0)->Method();
Run Code Online (Sandbox Code Playgroud)

此代码包含未定义的行为,因为它包括取消引用空指针(无论之后发生什么).这真的没有意义 - 演员是在那里将类型名称提供给编译器,并且编写上面代码的人可以写这个:

Class::Method();
Run Code Online (Sandbox Code Playgroud)

而后者也没关系.

为什么有人会写前代码?它是来自一些美好时光的已知成语还是什么?

c++ pointers static-members undefined-behavior dereference

57
推荐指数
1
解决办法
3033
查看次数

++ x%= 10在C++中定义良好吗?

在浏览某个项目的代码时,我遇到了以下声明:

++x %= 10;
Run Code Online (Sandbox Code Playgroud)

这个陈述是用C++很好地定义的,还是属于同一类别

a[i] = i++
Run Code Online (Sandbox Code Playgroud)

c++ evaluation undefined-behavior language-lawyer

56
推荐指数
5
解决办法
5617
查看次数

[a [0]] = 1会产生未定义的行为吗?

这个C99代码是否会产生未定义的行为?

#include <stdio.h>

int main() {
  int a[3] = {0, 0, 0};
  a[a[0]] = 1;
  printf("a[0] = %d\n", a[0]);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

在声明中a[a[0]] = 1;,a[0]都是读取和修改.

我看了ISO/IEC 9899的n1124草案.它说(在6.5表达式中):

在前一个和下一个序列点之间,对象的存储值最多只能通过表达式的计算来修改一次.此外,先前的值应该只读以确定要存储的值.

它没有提到读取对象来确定要修改的对象本身.因此,此语句可能会产生未定义的行为.

但是,我觉得很奇怪.这实际上是否会产生未定义的行为?

(我也想知道其他ISO C版本中的这个问题.)

c c99 undefined-behavior language-lawyer

56
推荐指数
4
解决办法
2611
查看次数