Sin(int)在Xcode调试器(lldb)中被破坏 [英] Sin(int) is broken in Xcode debugger (lldb)

查看:215
本文介绍了Sin(int)在Xcode调试器(lldb)中被破坏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个针对iOS SDK 6.1的通用iOS应用程序,编译器设置为 Apple LLVM编译器4.2 。当我在我的代码中放置一个断点并运行以下时,我会得到 sin(int)的奇怪结果。



作为参考, sin(70) = 0.7739 (70以弧度表示)

 (lldb)p(double)sin(70)
(double)$ 0 = -0.912706376367676 //初始值
(lldb)p (double)sin(1.0)
(double)$ 1 = 0.841470984807897 //重置值sin(int)将返回
(lldb)p(double)sin(70)
(double) $ 2 = 0.841470984807905 //返回与sin(1.0)相同
(lldb)p(double)sin(70.0)
(double)$ 3 = 0.773890681557889 //重置值sin(int)将返回
(lldb)p(double)sin(70)
(double)$ 4 = 0.773890681558519
(lldb)p(double)sin((float)60)
(double)$ 5 = -0.304810621102217 //铸造工作与添加.0相同
(lldb)p(double)sin(70)
(double)$ 6 = -0.30481062110269
(lldb)p double)sin(1)
(double)$ 7 = -0.304810621102223 //每个sin(int)的行为方式与

观察:




  • sin int)在调试会话中总是 -0.912706376367676

  • sin int)将始终返回从最后执行的 sin(float)返回的相同值。

  • 如果我用 po expr 替换 p (例如expr(double)sin(70)),我得到相同的确切结果。



为什么调试器的行为是这样的? p>

这是否意味着我每次调用函数时都应该输入每个参数的值?



一些更有趣的行为使用NSLog:

 (lldb)expr(void)NSLog(@%f,(float)sin(70)) 
0.000000 //新初始值
(lldb)expr(void)NSLog(@%f,(float)sin(70.0))
0.773891
(lldb)expr (void)NSLog(@%f,(float)sin(70))
0.000000 //不返回先前的sin(float)值
(lldb)p(double) )
(double)$ 0 = 1.48539705402154e-312 //受sin(float)影响的sin(int)不同的
(lldb)p(double)sin(70.0)
(double)$ 1 = 0.773890681557889
(lldb)expr(void)NSLog(@%f,(float)sin(70))
0.000000 //不受sin(float)影响


解决方案

你正在走进美妙的默认参数pr记住,记住,lldb不知道 sin()的参数类型或返回类型是什么。正确的原型是 double sin(double)。当你写

 (lldb)p(float)sin(70)
/ pre>

有两个问题。首先,您提供一个整数参数,C默认升级规则将作为一个 int 传递,相关架构上的4字节值。 double 除了是8个字节,是完全不同的编码。所以 sin 正在获得垃圾输入。第二, sin()在这些体系结构上返回一个 double 或8个字节,但是你告诉lldb抓住4个字节,做一些有意义的事情。如果你调用了 p(float)sin((double)70)(所以只有返回类型不正确)lldb会打印一个无意义的值,如9.40965e + 21的0.773891。



当你写了

 (lldb)p双)sin(70.0)

你修复了这些错误。浮点类型的默认C升级是将其作为 double 传递。如果你正在调用 sinf(),那么你会遇到问题,因为这个函数只有一个 float



如果你想为 sin()提供一个正确的原型,而不用担心这些问题,这很容易。将其添加到您的〜/ .lldbinit 文件,

 设置设置目标.expr-prefix〜/ lldb / prefix.h 

(我有一个 〜/ lldb 目录,我存储有用的python文件和这样的东西)和〜/ lldb / prefix.h 将读取

  externC{
int strcmp(const char *,const char *);
void printf(const char *,...);
双罪(双);
}

(你可以看到我也有我的前缀文件中的strcmp() printf(),所以我不需要投这些。)你也不想放很多东西在这里 - 这个文件是在lldb中评估的每一个表达式的前提下,如果把所有原型放在 / usr / include



将原型添加到我的 target.expr-prefix 设置:

 (lldb)p sin(70)
(double)$ 0 = 0.773890681557889


I have an universal iOS app targeting iOS SDK 6.1, and the compiler is set to Apple LLVM compiler 4.2. When I place a breakpoint in my code and run the following I get weird results for sin(int).

For reference, sin(70) = 0.7739 (70 is in radians).

(lldb) p (double)sin(70)
(double) $0 = -0.912706376367676 // initial value
(lldb) p (double)sin(1.0)
(double) $1 = 0.841470984807897 // reset the value sin(int) will return
(lldb) p (double)sin(70)
(double) $2 = 0.841470984807905 // returned same as sin(1.0)
(lldb) p (double)sin(70.0)
(double) $3 = 0.773890681557889 // reset the value sin(int) will return
(lldb) p (double)sin(70)
(double) $4 = 0.773890681558519
(lldb) p (double)sin((float)60)
(double) $5 = -0.304810621102217 // casting works the same as appending a ".0"
(lldb) p (double)sin(70)
(double) $6 = -0.30481062110269
(lldb) p (double)sin(1) 
(double) $7 = -0.304810621102223 // every sin(int) behaves the same way

Observations:

  • The first value for sin(int) in a debug session is always -0.912706376367676.
  • sin(int) will always return the same value that was returned from the last executed sin(float).
  • If I replace p with po, or expr (e.g. expr (double)sin(70)), I get the same exact results.

Why is the debugger behaving like this?

Does this mean that I should type cast every single parameter each time I call a function?

Some more interesting behavior with NSLog:

(lldb) expr (void)NSLog(@"%f", (float)sin(70))
0.000000 // new initial value
(lldb) expr (void)NSLog(@"%f", (float)sin(70.0))
0.773891
(lldb) expr (void)NSLog(@"%f", (float)sin(70))
0.000000 // does not return the previous sin(float) value
(lldb) p (double)sin(70)
(double) $0 = 1.48539705402154e-312 // sin(int) affected by sin(float) differently
(lldb) p (double)sin(70.0)
(double) $1 = 0.773890681557889
(lldb) expr (void)NSLog(@"%f", (float)sin(70))
0.000000 // not affected by sin(float)

解决方案

You're walking into the wonderful world of default argument promotions in C. Remember, lldb doesn't know what the argument types or return type of sin() is. The correct prototype is double sin (double). When you write

(lldb) p (float) sin(70)

there are two problems with this. First, you're providing an integer argument and the C default promotion rules are going to pass this as an int, a 4-byte value on the architectures in question. double, besides being 8-bytes, is an entirely different encoding. So sin is getting garbage input. Second, sin() returns a double, or 8-byte on these architectures, value but you're telling lldb to grab 4 bytes of it and do something meaningful. If you'd called p (float)sin((double)70) (so only the return type was incorrect) lldb would print a nonsensical value like 9.40965e+21 instead of 0.773891.

When you wrote

(lldb) p (double) sin(70.0)

you fixed these mistakes. The default C promotion for a floating point type is to pass it as a double. If you were calling sinf(), you'd have problems because the function expected only a float.

If you want to provide lldb with a proper prototype for sin() and not worry about these issues, it is easy. Add this to your ~/.lldbinit file,

settings set target.expr-prefix ~/lldb/prefix.h

(I have a ~/lldb directory where I store useful python files and things like this) and ~/lldb/prefix.h will read

extern "C" {
int strcmp (const char *, const char *);
void printf (const char *, ...);
double sin(double);
}

(you can see that I also have prototypes for strcmp() and printf() in my prefix file so I don't need to cast these.) You don't want to put too many things in here - this file is prepended to every expression you evaluate in lldb and it will slow your expression evaluations down if you put all the prototypes in /usr/include in there.

With that prototype added to my target.expr-prefix setting:

(lldb) p sin(70)
(double) $0 = 0.773890681557889

这篇关于Sin(int)在Xcode调试器(lldb)中被破坏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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