Отладка под macOS
If you experience crashes or issues in Electron that you believe are not caused by your JavaScript application, but instead by Electron itself, debugging can be a little bit tricky especially for developers not used to native/C++ debugging. However, using lldb
and the Electron source code, you can enable step-through debugging with breakpoints inside Electron's source code. You can also use XCode for debugging if you prefer a graphical interface.
Требования
-
A testing build of Electron: The easiest way is usually to build it from source, which you can do by following the instructions in the build instructions. 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. In this case 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: In addition to Xcode, you should also install the Xcode command line tools. They include LLDB, the default debugger in Xcode on macOS. Он поддерживает отладку C, Objective-C и C++ на настольных и iOS устройствах и симуляторах.
-
.lldbinit: Create or edit
~/.lldbinit
to allow Chromium code to be properly source-mapped.# e.g: ['~/electron/src/tools/lldb']
script sys.path[:0] = ['<...path/to/electron/src/tools/lldb>']
script import lldbinit
Подключение к Electron для отладки
To start a debugging session, open up Terminal and start lldb
, passing a non-release build of Electron as a parameter.
$ lldb ./out/Testing/Electron.app
(lldb) target create "./out/Testing/Electron.app"
Current executable set to './out/Testing/Electron.app' (x86_64).
Задание точек останова
LLDB is a powerful tool and supports multiple strategies for code inspection. For this basic introduction, let's assume that you're calling a command from JavaScript that isn't behaving correctly - so you'd like to break on that command's C++ counterpart inside the Electron source.
Соответствующие файлы кода можно найти в ./shell/
.
Let's assume that you want to debug app.setName()
, which is defined in browser.cc
as Browser::SetName()
. Set the breakpoint using the breakpoint
command, specifying file and line to break on:
(lldb) breakpoint set --file browser.cc --line 117
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:
(lldb) запуск
The app will immediately be paused, since Electron sets the app's name on launch:
(lldb) run
Process 25244 launched: '/Users/fr/Code/electron/out/Testing/Electron.app/Contents/MacOS/Electron' (x86_64)
Process 25244 stopped
* thread #1: tid = 0x839a4c, 0x0000000100162db4 Electron Framework`atom::Browser::SetName(this=0x0000000108b14f20, name="Electron") + 20 at browser.cc:118, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000100162db4 Electron Framework`atom::Browser::SetName(this=0x0000000108b14f20, name="Electron") + 20 at browser.cc:118
115 }
116
117 void Browser::SetName(const std::string& name) {
-> 118 name_override_ = name;
119 }
120
121 int Browser::GetBadgeCount() {
(lldb)
To show the arguments and local variables for the current frame, run frame variable
(or fr v
), which will show you that the app is currently setting the name to "Electron".
(lldb) frame variable
(atom::Browser *) this = 0x0000000108b14f20
(const string &) name = "Electron": {
[...]
}
To do a source level single step in the currently selected thread, execute step
(or s
). This would take you into name_override_.empty()
. To proceed and do a step over, run next
(or n
).
(lldb) step
Process 25244 stopped
* thread #1: tid = 0x839a4c, 0x0000000100162dcc Electron Framework`atom::Browser::SetName(this=0x0000000108b14f20, name="Electron") + 44 at browser.cc:119, queue = 'com.apple.main-thread', stop reason = step in
frame #0: 0x0000000100162dcc Electron Framework`atom::Browser::SetName(this=0x0000000108b14f20, name="Electron") + 44 at browser.cc:119
116
117 void Browser::SetName(const std::string& name) {
118 name_override_ = name;
-> 119 }
120
121 int Browser::GetBadgeCount() {
122 return badge_count_;