在iPhone发布版本中挂起的循环 [英] Empty while loop hangs in iPhone release build

查看:107
本文介绍了在iPhone发布版本中挂起的循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于某些原因,在发布版本中有一个空的while循环挂起,而在调试版本中使用它可以正常工作。此示例适用于调试但在发行版中挂起:

For some reason having an empty while loop in a release build hangs, while having it in the debug build works fine. This example works in debug but hangs in release:

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

这是我提出的解决方案,以使其在发布中发挥作用:

This is the solution I came up with in order to get it to work in release:

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

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

I am just curious why I would need to add something in the loop block of code.

推荐答案

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

The reason is of course due to compilers optimizations, as already noted in the comments.

记住Objective-C是建立在C之上的,我将一个简单的C示例放在一起,具有不同的优化级别,这就是结果。

Remembering that Objective-C is built on top of C, I put together a simple C example with different levels of optimizations and here's the result.

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



没有优化的LLVM IR(-O0)



LLVM IR with no optimizations (-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
}



LLVM IR with级别1优化(-O1)



LLVM IR with level 1 optimizations (-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
}

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

As you can see, the compiler produces an infinite loop when optimizing, since the local variable _isReadyForData is useless in that context and therefore is removed.

根据@faffaffaff的建议,在 _isReadyForData 上使用 volatile 关键字可以解决问题。

As suggested by @faffaffaff, using the volatile keyword on _isReadyForData may solve the issue.

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说你最好改变你的程序流程并使用驱动逻辑,而不是修改你已经拥有的东西。

But I definitely agree with @rmaddy in saying that you'd better change the flow of your program and use driven logic, instead of patching what you have already.

这篇关于在iPhone发布版本中挂起的循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆