无法在 Xcode 调试器中按名称解析枚举值

ard*_*new 4 xcode enums objective-c ios lldb

在整个项目中使用的全局头文件中使用枚举 typedef,我无法在 Xcode 中使用 lldb 时按名称引用各个枚举值。

例如,如果我在枚举类型可用的任何断点处停止,并且我尝试在 Xcode 的 lldb 提示符处评估某些内容(例如(lldb) p (int)EnumConstant),lldb 会抱怨:

error: use of undeclared identifier 'EnumConstant'
Run Code Online (Sandbox Code Playgroud)

此外,如果我尝试使用条件中的枚举常量设置条件断点(例如,在 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'
Run Code Online (Sandbox Code Playgroud)

当我开始在“编辑断点...”窗口中键入名称时,Xcode 的代码完成弹出窗口甚至解决了对枚举常量的建议,因此 Xcode 本身在解决它时没有问题。

是否有可以在 lldb 或 Xcode 中设置的选项,以便 lldb编译维护枚举标识符?我假设枚举常量在编译期间被转换为它们的序数值,导致可执行文件丢弃标识符,但这只是我天真的推测。

当我在 Linux 或 Cygwin 的简单 GNU C 程序中使用等效代码(显然减去类定义),但使用 gcc/gdb 而不是 Xcode/lldb 时,我没有这些问题。它能够解决枚举值没问题。


我创建了一个很小的 ​​Xcode iPhone 项目来演示我的意思。enum_tViewController.m上下文中使用以下任何常量(for 循环是演示的好地方)将产生相同的结果。

视图控制器.h:

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

typedef enum
{
    eZero, eOne, eTwo, eCOUNT
}
enum_t;

extern NSString const * const ENUM_STR[];

@end
Run Code Online (Sandbox Code Playgroud)

视图控制器.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
Run Code Online (Sandbox Code Playgroud)

Jim*_*ham 5

这是如何构建枚举的名称->调试信息查找加速器表的错误(相当长的时间)。虽然列出了枚举类型,但没有列出枚举值。这样做肯定是为了节省输出调试信息的大小——调试信息很快就会变得非常大,因此在添加更多信息的成本和更多信息的效用之间存在持续的紧张关系。到目前为止,这还没有上升到包含的水平。

无论如何,即使对于规模不错的项目,搜索“名称与'eZero'匹配的任何东西的所有调试信息”的速度都非常慢,而对于大型项目来说则非常糟糕。所以 lldb 总是使用这些 name->Debug Info 表作为它的第一级访问。

因为加速器表确实包含按名称的枚举类型(对您来说更重要的是按名称键入定义),解决方法是:

(lldb) expr enum_t::eZero (int) $0 = 0

当然,如果您有真正的匿名枚举,那么在将这些信息添加到加速器表之前,您就很不走运了。

顺便说一句,调试器控制台窗口中的 Xcode 符号完成是使用 Xcode SourceKit 索引器完成的,而不是 lldb。所以 Xcode 提供的补全并不反映 lldb 对程序的了解。

顺便说一句,gdb 不使用编译器制作的加速器表(这些是直到新的 DWARF 5 标准的 Apple 扩展),而是通过扫描调试信息手动构建索引。这允许他们索引对调试器来说最好的任何东西。OTOH,它使大型项目的调试器启动速度相当慢。