由于某种原因,在发布版本中有一个空的while循环挂起,而在调试版本中有它可以正常工作。此示例适用于调试但在发行版中挂起:
//Wait for stream to open
while (!_isReadyForData);
这是我提出的解决方案,以便在发布版本中使用它:
//Wait for stream to open
while (!_isReadyForData)
{
//For some reason in release mode, this is needed
sleep(.5);
}
我只是好奇为什么我需要在循环代码块中添加一些内容。
答案 0 :(得分:3)
原因当然是由于编译器的优化,正如评论中已经提到的那样。
记住Objective-C是建立在C之上的,我将一个简单的C示例与不同的优化级别放在一起,这就是结果。
int main(int argc, char const *argv[]) {
char _isReadyForData = 0;
while (!_isReadyForData);
return 0;
}
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
}
define i32 @main(i32 %argc, i8** nocapture %argv) #0 {
entry:
br label %while.cond
while.cond: ; preds = %while.cond, %entry
br label %while.cond
}
正如您所看到的,编译器在优化时会产生无限循环,因为局部变量_isReadyForData
在该上下文中无用,因此会被删除。
根据@faffaffaff的建议,使用volatile
上的_isReadyForData
关键字可以解决问题。
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的说法,你最好改变你的程序流程并使用驱动逻辑,而不是修改已经存在的东西。