空的while循环在iPhone版本构build中挂起

出于某种原因,在发布版本中有一个空的while循环会挂起,而在debugging版本中它可以正常工作。 这个例子在debugging中起作用,但在发行版中挂起:

//Wait for stream to open while (!_isReadyForData); 

这是我想出来的解决scheme,以使其在发行版中工作:

 //Wait for stream to open while (!_isReadyForData) { //For some reason in release mode, this is needed sleep(.5); } 

我只是好奇,为什么我需要在循环代码块中添加一些东西。

原因当然是由于编译器的优化,正如评论中已经提到的那样。

记住Objective-C是build立在C之上的,我把一个简单的C例子和不同的优化级别结合在一起,这就是结果。

原始代码

 int main(int argc, char const *argv[]) { char _isReadyForData = 0; while (!_isReadyForData); return 0; } 

没有优化的LLVM IR(-O0)

 define i32 @main(i32 %argc, i8** %argv) #0 { entry: %retval = alloca i32, align 4 %argc.addr = alloca i32, align 4 %argv.addr = alloca i8**, align 8 %_isReadyForData = alloca i8, align 1 store i32 0, i32* %retval store i32 %argc, i32* %argc.addr, align 4 store i8** %argv, i8*** %argv.addr, align 8 store i8 0, i8* %_isReadyForData, align 1 br label %while.cond while.cond: ; preds = %while.body, %entry %0 = load i8* %_isReadyForData, align 1 %tobool = icmp ne i8 %0, 0 %lnot = xor i1 %tobool, true br i1 %lnot, label %while.body, label %while.end while.body: ; preds = %while.cond br label %while.cond while.end: ; preds = %while.cond ret i32 0 } 

具有1级优化的LLVM IR(-O1)

 define i32 @main(i32 %argc, i8** nocapture %argv) #0 { entry: br label %while.cond while.cond: ; preds = %while.cond, %entry br label %while.cond } 

正如你所看到的,编译器在优化时会产生无限循环,因为局部variables_isReadyForData在该上下文中是无用的,因此被删除。

正如@faffaffaff所build议的那样,在_isReadyForData上使用volatile关键字可以解决这个问题。

具有易失性关键字的1级优化(-O1)的LLVM IR

 define i32 @main(i32 %argc, i8** nocapture %argv) #0 { entry: %_isReadyForData = alloca i8, align 1 store volatile i8 0, i8* %_isReadyForData, align 1 br label %while.cond while.cond: ; preds = %while.cond, %entry %_isReadyForData.0.load1 = load volatile i8* %_isReadyForData, align 1 %lnot = icmp eq i8 %_isReadyForData.0.load1, 0 br i1 %lnot, label %while.cond, label %while.end while.end: ; preds = %while.cond ret i32 0 } 

但我绝对同意@rmaddy的说法,你最好改变你的程序stream程,并使用驱动的逻辑,而不是修补已有的东西。