在整个项目中使用的全局头文件中使用枚举 typedef'd,在 Xcode 中使用 lldb 时,我无法按名称引用各个枚举值。
例如,如果我在枚举类型可用的任何断点处停止,并且我尝试在 Xcode 中的 lldb 提示符处评估某些内容(例如(lldb) p (int)EnumConstant
(,LLDB抱怨:
error: use of undeclared identifier 'EnumConstant'
此外,如果我尝试在条件中使用枚举常量设置条件断点(例如,在 Xcode 中右键单击断点>编辑断点...>条件:EnumConstant == someLocalVar
(,那么 Xcode 每次尝试在该断点处评估该条件时都会抱怨:
Stopped due to an error evaluating condition of breakpoint 1.1: "EnumConstant == someLocalVar"
Couldn't parse conditional expression:
error: use of undeclared identifier 'EnumConstant'
Xcode 的代码完成弹出窗口甚至解决了当我开始在"编辑断点..."中键入名称时枚举常量的建议。窗口,所以 Xcode 本身解决它没有问题。
是否有我可以在 lldb 或 Xcode 中设置的选项,以便 lldb在编译后维护枚举标识符?我假设枚举常量在编译过程中被转换为它们的序号值,导致可执行文件丢弃标识符,但这只是我幼稚的猜测。
当我在Linux或Cygwin的简单GNU C程序中使用等效代码时(显然减去类定义(,但是使用gcc/gdb而不是Xcode/lldb,我没有这些问题。它能够解决枚举值没有问题。
我创建了一个很小的 Xcode iPhone 项目来演示我的意思。在ViewController.m
上下文中使用下面的任何enum_t
常量(for-loop是演示的好地方(将产生相同的结果。
ViewController.h:
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
typedef enum
{
eZero, eOne, eTwo, eCOUNT
}
enum_t;
extern NSString const * const ENUM_STR[];
@end
ViewController.m:
#import "ViewController.h"
@implementation ViewController
NSString const * const ENUM_STR[eCOUNT] = { @"eZero", @"eOne", @"eTwo" };
- (void)viewDidLoad
{
[super viewDidLoad];
for (enum_t value = eZero; value < eCOUNT; ++value)
{
NSLog(@"%-8@ = %d", ENUM_STR[value], value);
}
}
@end
这是枚举的名称>调试信息查找加速器表构建方式中的一个错误(相当长期(。 虽然列出了枚举类型,但未列出枚举值。 这样做肯定是为了节省输出调试信息的大小 - 调试信息很快就会变得非常大,因此添加更多信息的成本与更多信息的效用之间存在持续的紧张关系。到目前为止,这个还没有上升到包容的水平。
无论如何,搜索"所有调试信息中名称与'eZero'匹配的任何内容"即使对于规模不错的项目来说也是非常缓慢的,对于大型项目来说真的很糟糕。 因此,lldb 始终使用这些名称>调试信息表进行第一级访问。
由于加速器表确实按名称包含枚举类型(对于按名称划分的 typedefs 也很重要(,因此解决方法是执行以下操作:
(lldb( expr enum_t::eZero (整数( $0 = 0
当然,如果你有真正的匿名枚举,那么在这些信息被添加到加速器表中之前,你几乎是不走运的。
顺便说一句,调试器控制台窗口中的 Xcode 符号完成是使用 Xcode SourceKit 索引器完成的,而不是 lldb。 因此,Xcode 提供的完成并不能反映 lldb 对该程序的了解。
BBTW,gdb不使用编译器制作的加速器表(这些是Apple的扩展,直到新的DWARF 5标准(,而是通过扫描调试信息手动构建索引。 这允许他们索引调试器认为最好的任何内容。 OTOH,它使大型项目的调试器启动速度变慢。