C ++程序员应该知道的所有常见的未定义行为是什么?
C ++程序员应该知道的所有常见的未定义行为是什么?
比如说:
a[i] = i++;
指针
NULL
指针 memcpy
复制重叠的缓冲区。 缓冲区溢出
整数溢出
int64_t i = 1; i <<= 72
未定义) 类型,演员和常量
int i; i++; cout << i;
) volatile
或sig_atomic_t
以外的任何类型对象的值 功能和模板
OOP
源文件和预处理
long int
表示的预处理器数值 #if
表达式中动态生成定义的标记 待分类
函数参数的评估顺序是未指定的行为 。 (这不会让你的程序崩溃,爆炸,或订购比萨...不像未定义的行为 。)
唯一的要求是,在调用函数之前,必须全面评估所有参数。
这个:
// The simple obvious one.
callFunc(getA(),getB());
可以等同于:
int a = getA();
int b = getB();
callFunc(a,b);
或这个:
int b = getB();
int a = getA();
callFunc(a,b);
它可以是; 这取决于编译器。 结果可能很重要,这取决于副作用。
编译器可以自由地对表达式的评估部分进行重新排序(假定其含义不变)。
从原来的问题来看:
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;
双重检查锁定。 而且容易犯一个错误。
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.
链接地址: http://www.djcxy.com/p/73201.html
上一篇: What are all the common undefined behaviours that a C++ programmer should know about?
下一篇: What is the difference between a sequence point and operator precedence?