yes*_*aaj 201 c++ c++-faq undefined undefined-behavior
C++程序员应该知道的所有常见的未定义行为是什么?
说,像:
a[i] = i++;
Run Code Online (Sandbox Code Playgroud)
Dio*_*lis 233
NULL
指针memcpy
复制重叠的缓冲区.int64_t i = 1; i <<= 72
,未定义)int i; i++; cout << i;
)volatile
或者sig_atomic_t
在收到的信号的long int
#if
表达式中动态生成已定义的标记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)
它可以是; 这取决于编译器.结果可能很重要,具体取决于副作用.
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)
剥离后const
使用const_cast<>
以下方式分配常量:
const int i = 10;
int *p = const_cast<int*>( &i );
*p = 1234; //Undefined
Run Code Online (Sandbox Code Playgroud)
除了未定义的行为,还有同样讨厌的实现定义的行为.
当程序执行标准未指定结果的事情时,会发生未定义的行为.
实现定义的行为是程序的一个动作,其结果不是由标准定义的,而是需要实现的文档.一个例子是"多字节字符文字",来自Stack Overflow问题是否有一个C编译器无法编译它?.
实现定义的行为只会在您开始移植时咬你(但升级到新版本的编译器也在移植!)
归档时间: |
|
查看次数: |
61252 次 |
最近记录: |