Xcode调试器(lldb)中的Sin(int)已损坏

Xcode调试器(lldb)中的Sin(int)已损坏,xcode,debugging,lldb,Xcode,Debugging,Lldb,我有一个针对iOS SDK 6.1的通用iOS应用程序,编译器设置为Apple LLVM compiler 4.2。当我在代码中放置一个断点并运行以下命令时,我得到了sin(int)的奇怪结果 作为参考,sin(70)=0.7739(70以弧度表示) 意见: 调试会话中sin(int)的第一个值总是-0.912706376367676 sin(int)将始终返回上次执行的sin(float)返回的值 如果我将p替换为po,或expr(例如expr(double)sin(70)),我会得到相同的

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

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

意见:

  • 调试会话中
    sin(int)
    的第一个值总是
    -0.912706376367676
  • sin(int)
    将始终返回上次执行的
    sin(float)
    返回的值
  • 如果我将
    p
    替换为
    po
    ,或
    expr
    (例如expr(double)sin(70)),我会得到相同的精确结果
为什么调试器的行为是这样的

这是否意味着我应该在每次调用函数时输入cast每个参数

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)

您正走进C中默认参数提升的奇妙世界。请记住,lldb不知道
sin()
的参数类型或返回类型是什么。正确的原型是
double sin(double)
。当你写作时

(lldb) p (float) sin(70)
这有两个问题。首先,您提供了一个整数参数,C默认升级规则将把它作为
int
传递,这是所讨论的体系结构上的一个4字节值
double
,除了是8字节之外,是一种完全不同的编码。因此,
sin
正在获取垃圾输入。其次,
sin()
在这些体系结构上返回一个
double
,或8字节的值,但您告诉lldb获取其中的4个字节并执行一些有意义的操作。如果调用
p(float)sin((double)70)
(因此只有返回类型不正确),lldb将打印一个无意义的值,如9.40965e+21,而不是0.773891

当你写信的时候

(lldb) p (double) sin(70.0)
你纠正了这些错误。浮点类型的默认C升级是将其作为
double
传递。如果调用的是
sinf()
,则会出现问题,因为函数只需要一个
浮点值

如果您想为lldb提供一个适当的
sin()
原型,而不必担心这些问题,那么这很容易。将其添加到您的
~/.lldbinit
文件中

settings set target.expr-prefix ~/lldb/prefix.h
(我有一个
~/lldb
目录,在那里我存储有用的python文件和类似的东西)并且
~/lldb/prefix.h
将读取

extern "C" {
int strcmp (const char *, const char *);
void printf (const char *, ...);
double sin(double);
}
(您可以看到,我的前缀文件中还有
strcmp()
printf()
的原型,所以我不需要强制转换这些原型。)你不想在这里放太多东西-这个文件是在你在lldb中计算的每个表达式前面加上的,如果你把所有原型都放在
/usr/include
中,它会减慢你的表达式计算速度

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

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

po命令用于打印对象-请改用“p”。此外,sin接受弧度的参数,因此sin(90)不应为zero@Vladimir:p也是这样,我更新了代码以反映这一点。我知道sin会吸收弧度,这就是为什么第一个输出很奇怪的原因。请向苹果公司提交一个bug+1.请详细解释。虽然我对C一无所知,但这是有道理的。我知道谁会给出答案:-)-所以即使我在源文件中包含math.h,lldb也不“知道”原型?如果我在我的项目中定义了一个函数
double mysin(double x)
,为什么不会出现这个问题?如果这些都是愚蠢的问题,很抱歉:-)原型(例如来自
)由于空间原因不会出现在调试信息中(如果您认为dSYM现在很大…)-但是您自己的函数会生成完整的调试信息,以便lldb知道所有参数的类型和返回类型。
(lldb) p sin(70)
(double) $0 = 0.773890681557889