Dio*_*lis 233

指针

  • 取消引用NULL指针
  • 取消引用由大小为零的"新"分配返回的指针
  • 使用指向生命周期已结束的对象的指针(例如,堆栈已分配的对象或已删除的对象)
  • 取消引用尚未明确初始化的指针
  • 执行指针运算,在数组的边界(上方或下方)之外产生结果.
  • 在超出数组末尾的位置取消引用指针.
  • 将指针转换为不兼容类型的对象
  • 使用memcpy复制重叠的缓冲区.

缓冲区溢出

  • 以负数或超出该对象大小的偏移量读取或写入对象或数组(堆栈/堆溢出)

整数溢出

  • 有符号整数溢出
  • 评估未在数学上定义的表达式
  • 左移值为负数(向右移位负值是实现定义的)
  • 将值移动大于或等于数字中的位数(例如int64_t i = 1; i <<= 72,未定义)

类型,演员和Const

  • 将数值转换为无法由目标类型表示的值(直接或通过static_cast)
  • 在明确分配之前使用自动变量(例如int i; i++; cout << i;)
  • 使用比其他类型的任何对象的值volatile或者sig_atomic_t在收到的信号的
  • 尝试在其生命周期内修改字符串文字或任何其他const对象
  • 在预处理期间将窄字符串与宽字符串文字连接起来

功能和模板

  • 不从值返回函数返回值(直接或通过从try块中流出)
  • 同一实体的多个不同定义(类,模板,枚举,内联函数,静态成员函数等)
  • 模板实例化中的无限递归
  • 使用不同的参数调用函数或链接到函数定义为使用的参数和链接.

OOP

  • 具有静态存储持续时间的对象的级联破坏
  • 分配给部分重叠的对象的结果
  • 在其静态对象的初始化期间递归地重新进入函数
  • 从构造函数或析构函数中对对象的纯虚函数进行虚函数调用
  • 指未经建造或已被破坏的物体的非静止构件

源文件和预处理

  • 非空源文件,不以换行符结尾,或以反斜杠结尾(在C++ 11之前)
  • 反斜杠后跟一个字符,该字符不是字符或字符串常量中指定的转义码的一部分(这是在C++ 11中实现定义的).
  • 超出实现限制(嵌套块的数量,程序中的函数数量,可用的堆栈空间......)
  • 预处理器数值,不能用a表示 long int
  • 类似函数的宏定义左侧的预处理指令
  • #if表达式中动态生成已定义的标记

待分类

  • 在销毁具有静态存储持续时间的程序期间调用exit


Mar*_*ork 31

评估函数参数的顺序是未指定的行为.(这不会使您的程序崩溃,爆炸或订购披萨......与未定义的行为不同.)

唯一的要求是在调用函数之前必须完全评估所有参数.


这个:

// The simple obvious one.
callFunc(getA(),getB());
Run Code Online (Sandbox Code Playgroud)

可以相当于:

int a = getA();
int b = getB();
callFunc(a,b);
Run Code Online (Sandbox Code Playgroud)

或这个:

int b = getB();
int a = getA();
callFunc(a,b);
Run Code Online (Sandbox Code Playgroud)

它可以是; 这取决于编译器.结果可能很重要,具体取决于副作用.

  • 订单未指定,未定义. (23认同)
  • 那非常讨厌. (2认同)
  • @Rob:我会和你争论这里意义的变化,但我知道标准委员会对这两个词的确切定义非常挑剔.所以我只是改变它:-) (2认同)
  • 我很幸运.当我在大学时,我被一个教授看了一眼,并在大约5秒内告诉我我的问题.不知道我会浪费多少时间来浪费调试. (2认同)

Mar*_*ork 27

编译器可以自由地重新排序表达式的求值部分(假设含义不变).

从原来的问题:

a[i] = i++;

// This expression has three parts:
(a) a[i]
(b) i++
(c) Assign (b) to (a)

// (c) is guaranteed to happen after (a) and (b)
// But (a) and (b) can be done in either order.
// See n2521 Section 5.17
// (b) increments i but returns the original value.
// See n2521 Section 5.2.6
// Thus this expression can be written as:

int rhs  = i++;
int lhs& = a[i];
lhs = rhs;

// or
int lhs& = a[i];
int rhs  = i++;
lhs = rhs;
Run Code Online (Sandbox Code Playgroud)

双重检查锁定.一个容易犯的错误.

A* a = new A("plop");

// Looks simple enough.
// But this can be split into three parts.
(a) allocate Memory
(b) Call constructor
(c) Assign value to 'a'

// No problem here:
// The compiler is allowed to do this:
(a) allocate Memory
(c) Assign value to 'a'
(b) Call constructor.
// This is because the whole thing is between two sequence points.

// So what is the big deal.
// Simple Double checked lock. (I know there are many other problems with this).
if (a == null) // (Point B)
{
    Lock   lock(mutex);
    if (a == null)
    {
        a = new A("Plop");  // (Point A).
    }
}
a->doStuff();

// Think of this situation.
// Thread 1: Reaches point A. Executes (a)(c)
// Thread 1: Is about to do (b) and gets unscheduled.
// Thread 2: Reaches point B. It can now skip the if block
//           Remember (c) has been done thus 'a' is not NULL.
//           But the memory has not been initialized.
//           Thread 2 now executes doStuff() on an uninitialized variable.

// The solution to this problem is to move the assignment of 'a'
// To the other side of the sequence point.
if (a == null) // (Point B)
{
    Lock   lock(mutex);
    if (a == null)
    {
        A* tmp = new A("Plop");  // (Point A).
        a = tmp;
    }
}
a->doStuff();

// Of course there are still other problems because of C++ support for
// threads. But hopefully these are addresses in the next standard.
Run Code Online (Sandbox Code Playgroud)


yes*_*aaj 5

剥离后const使用const_cast<>以下方式分配常量:

const int i = 10; 
int *p =  const_cast<int*>( &i );
*p = 1234; //Undefined
Run Code Online (Sandbox Code Playgroud)


Dan*_*ker 5

我最喜欢的是"模板实例化中的无限递归"因为我相信它是唯一一个在编译时发生未定义行为的人.

  • 不适合int的预处理器常量也是编译时. (2认同)

Con*_*tin 5

除了未定义的行为,还有同样讨厌的实现定义的行为.

当程序执行标准未指定结果的事情时,会发生未定义的行为.

实现定义的行为是程序的一个动作,其结果不是由标准定义的,而是需要实现的文档.一个例子是"多字节字符文字",来自Stack Overflow问题是否有一个C编译器无法编译它?.

实现定义的行为只会在您开始移植时咬你(但升级到新版本的编译器也在移植!)