调试Inkscape
要获取Inkscape的调试符号,您可能需要重新编译它。我们使用cmake,它具有生成调试符号的调试模式:
克马克-DCMAKE_BUILD_TYPE=调试/
这假设您正在构建构建文件夹中的所有内容,并且存储库根目录是父目录。
如果您正在查找较旧的非cmake版本,则需要手动启用CXXFLAGS。
使用Windows调试
有关Visual Studio调试,请参见Windows调试指南.
使用GDB调试
要开始用GDB调试Inkscape,请加载它:
gdb路径/to/inkscape
如果您希望Inkscape立即启动,并且您的GDB版本足够新,可以从以下开始
gdb路径/to/inkscape-ex r
要防止gdb分页(将命令的输出拆分为页面,使为错误报告创建回溯变得更加困难),可以将其放在~/.gdbinit中:
关闭分页
要使用GDB的文本UI,可以运行gdb-tui公司
或gdbtui公司
.
当程序崩溃时,您可能会看到如下内容:
程序接收到信号SIGSEGV,分段故障。0x00000000000000英寸??(gdb)
要找出崩溃发生的位置(您可能并不总是能够找到),您应该运行:
(gdb)回溯
或
(gdb)其中
或
(gdb)bt公司
每一个都执行相同的操作,并引用命令回溯
.
使用GDB进行更高级的调试
当你运行bt时,你会得到一个帧列表:
程序接收到信号SIGTRAP,跟踪/断点陷阱。位于../..的SPDesktopWidget::createInstance(namedview=0x33a57a0)中的0x000000000aa849f/src/widgets/desktop-widget.cpp:17081708 UXManager::getInstance()->连接到桌面(工具箱,dtw->桌面);(gdb)bt公司#位于../..的SPDesktopWidget::createInstance(namedview=0x33a57a0)中的0 0x000000000aa849f/src/widgets/desktop-widget.cpp:1708#位于../..的sp_desktop_widget_new(namedview=0x3a57a0)中的1 0x0000000000aa8065/src/widgets/desktop-widget.cpp:1659#位于../..的sp_file_new(templ=…)中的2 0x00000000052430d/src/file.cpp:155#位于../..的sp_file_new_default()中的3 0x0000000005249ba/src/file.cpp:226#位于../..的sp_main_gui中的4个0x00000000048865e(argc=1,argv=0x7fffffe0b8)/src/main.cpp:1071#5 0x000000000487fab在../..主设备中(argc=1,argv=0x7fffffe0b8)/src/main.cpp:789(gdb)
这些帧都是可选的:
(gdb)帧2#位于../..的sp_file_new(templ=…)中的2 0x00000000052430d/src/file.cpp:155
(如果您在更适合您的平台的调试器中发生相同的崩溃,可以使用选择帧
指定GDB找不到的地址。)
现在您已经激活了第2帧。您可以看到第2帧中处理器寄存器的状态以及编译器嵌入到调试符号中的任何局部变量。
(gdb)信息局部变量文档=0x27fbea0myRoot=0x27f8850nodeToRemove=0x0旧桌面=0x0dtw=0x7fffffffdd30桌面=0x33a0710(gdb)打印模板$1=(const std::string&)@0x7fffffddb8:{static npos=18446744073709551615,_M_dataplus={<std:;allocator<char>>={<__gnu_cxx::new_allocator<char>={无数据字段>},<无数据字段>},_M_p=0x339fdd8“/usr/local/share/inkscape/templates/default.svg”}
单步执行和断点
有时,您希望控制程序的执行,而不是让它疯狂运行。
您可以告诉GDB在到达某个函数时、在某个条件下或当内存中的值发生更改时停止。这些被称为断点和观察点。
调用函数时停止:
(gdb)中断Inkscape::UI::Tools::SelectTool::root_handler0xf64ab7处的断点1:file..//src/ui/tools/select-tool.cpp,第460行。
如果抛出任何异常,则停止:
(gdb)接球投掷接球点2(投掷)
满足条件时停止:
(gdb)中断..//src/ui/tools/select-tool.cpp:629,如果group_at_point==00xf657a5处的断点3:file..//src/ui/tools/select-tool.cpp,第629行。
内存值更改时停止:
(gdb)打印桌面$2=(SPDesktop*)0x33a0710(gdb)awatch*0x33a0710硬件访问(读/写)监视点4:*0x33a0710
列出断点:
(gdb)信息中断数字类型显示Enb地址什么1个断点将y 0x000000000f64ab7保留在Inkscape::UI::Tools::SelectTool::root_handler(_GdkEvent*)中的..//src/ui/tools/select-tool.cpp:4602断点保持y 0x00007ffff03a4a30异常抛出3断点将y 0x000000000f657a5保留在Inkscape::UI::Tools::SelectTool::root_handler(_GdkEvent*)中的..//src/ui/tools/select-tool.cpp:629仅当group_at_point==0时停止4 acc观察点保持y*0x33a0710
禁用断点:
(gdb)禁用4
删除断点:
(gdb)删除3
创建仅停止一次的断点:
(gdb)tbreak foo::bar(gdb)tcatch抛出
计算表达式
如果GDB能知道你在说什么,它几乎可以打印任何东西。GDB也不受类的私有边界的影响。
(gdb)打印arc_context->arc$3=(SPGenericEllipse*)0x3afb610
尝试确定堆对象是否仍然存在(尚未删除()d)的一个方便功能是使用新的GDB命令信息vtbl
:
(gdb)打印UXManager::getInstance()$4=(Inkscape::UI::UXManager*)0x3b6f1d0(gdb)信息vtbl$4用于“Inkscape::UI::UXManager”@0x136e500(子对象@0x3b6f1d0)的vtable:[0]:0xbc7720<Inkscape::UI::UXManagerImpl::~UXManager Impl()>[1] :0xbc7740<Inkscape::UI::UXManagerImpl::~UXManager Impl()>[2] :0xbc81e0<Inkscape::UI::UXManagerImpl::addTrack(SPDesktopWidget*)>…
下面是delete()d对象的vtable的样子:
(gdb)调用“operator delete”($4)(gdb)信息vtbl$4“Inkscape::UI::UXManager”@0x3f27f80的vtable(子对象@0x3b6f1d0):[0]:0x190[1] :0x20[2] :0x3d91db0[3] :0x0[4] :0x448d40<g_free@plt>…