• 在 macOS 中调试
    • 要求
    • 附加并调试 Electron
      • 设置断点
      • 进一步阅读

    在 macOS 中调试

    如果你在 Electron 中遇到问题或者引起崩溃,你认为它不是由你的JavaScript应用程序引起的,而是由 Electron 本身引起的。调试可能有点棘手,特别是对于不习惯 native/C++ 调试的开发人员。 然而,使用 lldb 和 Electron 源代码,可以在 Electron 的源代码中使用断点启用逐步调试。 如果您希望用图形界面的开发工具,也可以使用XCode for debugging。

    要求

    • Electron 的调试版本: 最简单的方法是自己构建它,使用 macOS 的构建说明 中列出的工具和先决条件要求。 While you can attach to and debug Electron as you can download it directly, you will find that it is heavily optimized, making debugging substantially more difficult: The debugger will not be able to show you the content of all variables and the execution path can seem strange because of inlining, tail calls, and other compiler optimizations.

    • Xcode: 除了 Xcode,还安装 Xcode 命令行工具. 它们包括 LLDB,在 Mac OS X 的 Xcode 中的默认调试器。它支持在桌面和iOS设备和模拟器上调试 C,Objective-C 和 C++。

    附加并调试 Electron

    要启动调试会话,打开命令行并启动 lldb ,并传递一个调试版本的 Electron 作为参数。

    1. $ lldb ./out/Debug/Electron.app
    2. (lldb) target create "./out/Debug/Electron.app"
    3. Current executable set to './out/Debug/Electron.app' (x86_64).

    设置断点

    LLDB是一个强大的工具,支持进行多种策略的代码检查。 在这做一个基本的介绍,让我们假设你从 JavaScript 调用一个不正常的命令 - 所以你想打断该命令的 C++ 对应的 Electron 源。

    Relevant code files can be found in ./atom/.

    让我们假设你想调试 app.setName(), 在 browser.cc 中定义为 Browser::SetName(). 使用 breakpoint 命令进行断点,指定文件和断点位置:

    1. (lldb) breakpoint set --file browser.cc --line 117
    2. Breakpoint 1: where = Electron Framework`atom::Browser::SetName(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) + 20 at browser.cc:118, address = 0x000000000015fdb4

    然后, 启动 Electron:

    1. (lldb) run

    应用程式会立即暂停,因为 Electron 会在启动时设定应用程序名称:

    1. (lldb) run
    2. Process 25244 launched: '/Users/fr/Code/electron/out/Debug/Electron.app/Contents/MacOS/Electron' (x86_64)
    3. Process 25244 stopped
    4. * thread #1: tid = 0x839a4c, 0x0000000100162db4 Electron Framework`atom::Browser::SetName(
    5. this=0x0000000108b14f20, name="Electron"
    6. ) + 20 at browser.cc:118, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    7. frame #0: 0x0000000100162db4 Electron Framework`atom::Browser::SetName(
    8. this=0x0000000108b14f20, name="Electron"
    9. ) + 20 at browser.cc:118
    10. 115 }
    11. 116
    12. 117 void Browser::SetName(const std::string& name) {
    13. -> 118 name_override_ = name;
    14. 119 }
    15. 120
    16. 121 int Browser::GetBadgeCount() {
    17. (lldb)

    显示当前帧的参数和局部变量, 运行 frame variable (或 fr v), 这将显示你的应用程序当前设置名称为 “Electron”.

    1. (lldb) frame variable
    2. (atom::Browser *) this = 0x0000000108b14f20
    3. (const string &) name = "Electron": {
    4. [...]
    5. }

    在当前选择的线程中执行源级单步执行, 执行 step (或 s). 这将带你进入 nameoverride.empty()。 继续前进,步过,运行 next (或 n).

    1. (lldb) step
    2. Process 25244 stopped
    3. * thread #1: tid = 0x839a4c, 0x0000000100162dcc Electron Framework`atom::Browser::SetName(
    4. this=0x0000000108b14f20, name="Electron"
    5. ) + 44 at browser.cc:119, queue = 'com.apple.main-thread', stop reason = step in
    6. frame #0: 0x0000000100162dcc Electron Framework`atom::Browser::SetName(
    7. this=0x0000000108b14f20, name="Electron"
    8. ) + 44 at browser.cc:119
    9. 116
    10. 117 void Browser::SetName(const std::string& name) {
    11. 118 name_override_ = name;
    12. -> 119 }
    13. 120
    14. 121 int Browser::GetBadgeCount() {
    15. 122 return badge_count_;

    要完成此时的调试,运行 process continue。 你也可以继续,直到这个线程中的某一行被命中(线程直到100)。 此命令将在当前帧中运行线程,直到它到达此帧中的行100,或者如果它离开当前帧,则停止。

    现在,如果你打开 Electron 的开发工具并调用 setName,你将再次命中断点。

    进一步阅读

    LLDB是一个强大的工具,有一个庞大的文档。 要了解更多信息,请参考 Apple 的调试文档, 例如 LLDB Command Structure Reference 或 Using LLDB as a Standalone Debugger.

    你也可以查看LLDB的 manual and tutorial 这将解释更复杂的调试场景.