C语言程序未被定义,C+程序员应该知道哪些常见的未定义行为?

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

根据原来的问题:

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.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值