相关疑难解决方法(0)

初始化是否需要左值到右值的转换?是`int x = x;`UB?

C++标准包含一个半着名的例子,在3.3.2中的"令人惊讶的"名称查找,"声明点":

int x = x;
Run Code Online (Sandbox Code Playgroud)

这初始化x自身,(原始类型)未初始化,因此具有不确定的值(假设它是一个自动变量).

这实际上是未定义的行为吗?

根据4.1"左值到右值转换",对未初始化的值执行左值到右值的转换是未定义的行为.右手是否x接受这种转换?如果是这样,示例实际上会有未定义的行为吗?

c++ initialization undefined-behavior language-lawyer

55
推荐指数
2
解决办法
2411
查看次数

如果要在多个平台上部署,未定义的行为只是一个问题吗?

围绕未定义行为(UB)的大多数对话都讨论了如何有一些平台可以做到这一点,或者一些编译器会这样做.

What if you are only interested in one platform and only one compiler (same version) and you know you will be using them for years?

Nothing is changing but the code, and the UB is not implementation-defined.

Once the UB has manifested for that architecture and that compiler and you have tested, can't you assume that from then on whatever the compiler did with the UB the first time, it will do that every time?

Note: I …

c++ undefined-behavior

51
推荐指数
5
解决办法
3216
查看次数

<stddef.h>中的'offsetof'宏是否会调用未定义的行为?

来自MSVC实施的示例:

#define offsetof(s,m) \
    (size_t)&reinterpret_cast<const volatile char&>((((s *)0)->m))
//                                                   ^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)

可以看出,它取消引用空指针,通常会调用未定义的行为.这是规则的例外还是正在发生的事情?

c++ offsetof undefined-behavior

18
推荐指数
2
解决办法
2273
查看次数

为什么编译器不再使用严格的别名来优化此UB

谷歌严格别名的第一个结果之一就是这篇文章 http://dbp-consulting.com/tutorials/StrictAliasing.html
我注意到的一个有趣的事情是:http://goo.gl/lPtIa5

uint32_t swaphalves(uint32_t a) {
  uint32_t acopy = a;
  uint16_t* ptr = (uint16_t*)&acopy;
  uint16_t tmp = ptr[0];
  ptr[0] = ptr[1];
  ptr[1] = tmp;
  return acopy;
}
Run Code Online (Sandbox Code Playgroud)

被编译为

swaphalves(unsigned int):
        mov     eax, edi
        ret
Run Code Online (Sandbox Code Playgroud)

由GCC 4.4.7.任何比这更新的编译器(文章中提到的4.4所以文章没有错)都没有实现该功能,因为它可以使用严格别名.这是什么原因?它实际上是GCC中的错误还是GCC决定放弃它,因为许多行代码是以产生UB的方式编写的,或者它只是一个持续多年的编译器回归...而Clang也没有优化它.

c c++ gcc clang strict-aliasing

16
推荐指数
2
解决办法
1054
查看次数

在C中除以零和未定义的行为

本文中,以下是一段可以触发除零的代码示例:

if (arg2 == 0)
    ereport(ERROR, (errcode(ERRCODE_DIVISION_BY_ZERO),
                    errmsg("division by zero")));
/* No overflow is possible */
PG_RETURN_INT32((int32) arg1 / arg2);
Run Code Online (Sandbox Code Playgroud)

ereport这是一个宏,它扩展为对 - bool返回函数的调用,该函数errstart可能会或可能不会返回,并且?:对其返回值有条件(使用a ),调用另一个函数.在这种情况下,我认为ereport水平ERROR无条件地导致longjmp()其他地方.

因此,对上述代码的简单解释是,如果arg2非零,则将发生除法并返回结果,而如果arg2为零,则将报告错误并且不会发生除法.然而,链接的论文声称C编译器可以在零检查之前合法地提升除法,然后推断零检查从未被触发.他们唯一的推理似乎是不正确的

程序员没有通知编译器对ereport的调用(ERROR,:: :)没有返回.这意味着除法将始终执行.

John Regehr有一个更简单的例子:

void bar (void);
int a;
void foo3 (unsigned y, unsigned z)
{
  bar();
  a = y%z;
}
Run Code Online (Sandbox Code Playgroud)

根据这篇博文,clang在调用之上提升了模运算bar,并且他展示了一些汇编代码来证明它.

我对C的理解是适用于这些片段的

  1. 没有或不可以返回的函数在标准C中是格式良好的,并且这样的声明不需要特定的属性,钟声或哨声.

  2. 调用不返回或不返回的函数的语义是明确定义的,特别是通过C99中的6.5.2.2"函数调用".

  3. 由于ereport调用是一个完整的表达式,因此有一个序列点;.类似地,由于barJohn Regehr的代码中的调用是一个完整的表达式,因此在该处有一个序列点 …

c undefined-behavior language-lawyer

13
推荐指数
1
解决办法
517
查看次数

如果它调用共享库,C++中的无限循环仍然是未定义的行为吗?

据说无限循环for(;;);是未定义的行为.


来自http://en.cppreference.com/w/cpp/language/memory_model

在有效的C++程序中,每个线程最终都会执行以下操作之一:

  • 终止
  • 调用I/O库函数
  • 读取或修改易失性对象
  • 执行原子操作或同步操作

没有执行任何这些可观察的行为,任何执行线程都不能永远执行.

请注意,这意味着具有无限递归或无限循环的程序(无论是作为for语句实现还是通过循环goto或其他方式)具有未定义的行为.


但是如果它在共享库中调用函数呢?

for(;;) sofunc();

该函数可以执行任何类型的阻塞I/O或抛出异常.

在这种情况下,编译器是否假定循环具有一些可观察的行为?

c++ infinite-loop undefined-behavior

12
推荐指数
1
解决办法
1673
查看次数

读取不确定值的未定义行为?

这个问题出现在问题答案的评论中.当类型转换为int时,C/C++ bool类型总是保证为0或1吗?

有问题的代码在bool不初始化其值的情况下分配(本地)数组.

const int n = 100;
bool b[n];
Run Code Online (Sandbox Code Playgroud)

显然,价值观b是不确定的.

一些评论者认为阅读b[0]是不明确的行为.这是在C++标准中的任何地方陈述的吗?我仍然相信相反:

  1. 显然存储已分配,并且基本bool类型的初始化已完成,因为它没有构造函数.因此,它肯定与取消引用未初始化的指针或在未初始化的非平凡对象上调用方法/强制转换操作符不同.标准似乎涵盖了这些具体案例.

  2. C中的行为确实未定义:C中声明的未初始化变量会发生什么?它有价值吗?一些受访者似乎对这两者感到困惑.

  3. 在最新的C++ 0x草案中,我找不到不确定值的定义,尤其是没有允许访问这样的值来触发处理器陷阱的定义.事实上,Bjarne的Stroustrup的是不知道的inderminate值可能是什么:http://zamanbakshifirst.blogspot.com/2007/02/c-indeterminate-value.html

c++ initialization undefined-behavior

11
推荐指数
3
解决办法
1501
查看次数

C和C++函数没有return语句

在查看工作代码时,我发现了一些(看似)令人反感的代码,其中函数具有返回类型,但没有返回.我知道代码有效,但认为它只是编译器中的一个错误.

我编写了以下测试并使用我的编译器运行它(gcc(Homebrew gcc 5.2.0)5.2.0)

#include <stdio.h>

int f(int a, int b) {
  int c = a + b;
}

int main() {
   int x = 5, y = 6;

   printf("f(%d,%d) is %d\n", x, y, f(x,y)); // f(5,6) is 11

   return 0;
}
Run Code Online (Sandbox Code Playgroud)

类似于我在工作中发现的代码,这默认返回函数中执行的最后一个表达式的结果.

我发现了这个问题,但对答案不满意.我知道-Wall -Werror可以避免这种行为,但为什么它是一个选项呢?为什么这仍然允许?

c c++ return

9
推荐指数
2
解决办法
9820
查看次数

以下C联合访问模式是否未定义行为?

以下是现代C中未定义的行为:

union foo
{
    int i;
    float f;
};
union foo bar;
bar.f = 1.0f;
printf("%08x\n", bar.i);
Run Code Online (Sandbox Code Playgroud)

并打印1.0f的十六进制表示.

但是以下是未定义的行为:

int x;
printf("%08x\n", x);
Run Code Online (Sandbox Code Playgroud)

那这个呢?

union xyzzy
{
    char c;
    int i;
};
union xyzzy plugh;
Run Code Online (Sandbox Code Playgroud)

这应该是未定义的行为,因为没有plugh编写成员.

printf("%08x\n", plugh.i);
Run Code Online (Sandbox Code Playgroud)

但是这个呢.这是未定义的行为吗?

plugh.c = 'A';
printf("%08x\n", plugh.i);
Run Code Online (Sandbox Code Playgroud)

现在大多数C编译器都有sizeof(char) < sizeof(int),sizeof(int)或者是2或4.这意味着在这些情况下,最多plugh.i会写入50%或25%,但读取剩余的字节将读取未初始化的数据,因此应该是未定义的行为.在此基础上,是整个读取未定义的行为?

c undefined-behavior unions language-lawyer type-punning

7
推荐指数
1
解决办法
320
查看次数

未初始化的变量如何获得随机值?

假设我声明了一个变量x并保持未初始化.我继续打印它的价值.我看到一些垃圾.

它从何而来?为什么它不用于生成随机数?我的意思是代替使用伪随机生成器.

c initialization undefined-behavior

6
推荐指数
1
解决办法
955
查看次数