vsc++调试没有调试界面
命令行界面是调试的有用工具,但没有什么能像精心设计的图形环境那样散发出专业性和精致感。 从头开始构建功能全面的调试环境需要花费大量时间和精力,但是还有一种选择:Eclipse C / C ++开发工具(CDT)。 CDT的可扩展性允许您将其图形调试功能连接到自定义调试器。 这不需要很多代码,但是您需要了解CDT的扩展点和CDI。
CDI是基于Java™的应用程序编程接口(API),其类和接口使访问CDT的调试框架成为可能。 使用CDI的Eclipse插件可以将新的调试器添加到CDT的操作中,并在Eclipse / CDT调试透视图中显示调试结果。 本文详细介绍了CDI。 该“ 与CDT调试器接口 ”系列的第2部分展示了CDI如何通过其机器接口(MI)专门用于GNU调试器(gdb)的接口。
学习CDT调试器如何工作的最好方法是查看并试验实际代码。 本文介绍了如何构建功能不足的插件,该插件扩展了CDT以提供基本的调试功能。 没有实际的调试器可执行文件,但是您可以使用此代码作为将自己的自定义调试器添加到CDT的基础。
该示例插件由CDT和Eclipse Debug Framework的三个扩展组成:
org.eclipse.debug.core.launchConfigurationTypes
org.eclipse.debug.ui.launchConfigurationTabGroups
org.eclipse.cdt.debug.core.CDebugger
本文介绍了每种方法,并提供了示例代码说明它们如何工作。 然后深入研究CDI的操作,涵盖CDI模型并研究CDI如何使断点和观察点成为可能。
在Eclipse中,启动应用程序的过程称为在运行模式下启动应用程序。 调试会话称为“ 调试”模式下的启动。 选择启动模式后,下一步就是选择启动配置类型。 这准确地告诉Eclipse应用程序应如何执行或调试。 例如,“调试”模式的启动配置类型定义了调试器可执行文件,默认调试选项以及应如何在Eclipse中显示调试输出。 图1显示了“ CDT调试配置”窗口中显示的配置类型。
要将新的调试器与Eclipse接口,第一步是创建新的启动配置类型。 这需要一个扩展org.eclipse.debug.core.launchConfigurationTypes
扩展点的插件。 在图1中,您可以在窗口左侧看到示例配置类型。 清单1显示了定义此新类型的扩展。
LaunchConfigurationType
扩展
由于将modes
字段设置为debug
并将public
字段设置为true
,因此将示例配置类型放置在Debug窗口中。 最重要的字段是delegate
,它标识管理启动过程的类。 此类必须实现ILaunchConfigurationDelegate
接口,并且从头开始编写委托可能很复杂。 值得庆幸的是,CDT通过提供四个预构建的委托类使您的生活更轻松:
LocalRunLaunchDelegate
LocalAttachLaunchDelegate
CoreFileLaunchDelegate
LocalCDILaunchDelegate
CDT将前三个用于本地软件启动。 最后一个代表是为CDT之外的工具创建的,并且是此讨论的重点。 当调用LocalCDILaunchDelegate
以调试模式启动时,它获得有关要调试的可执行文件和要发送到调试器的参数的信息。 此信息必须打包在ILaunchConfiguration
对象中,并且需要合适的UI才能从用户那里获取此信息。
在调试Eclipse应用程序之前,必须选择启动配置类型,然后通过双击或右键单击来创建新的启动配置。 此时,右侧将出现一个图形面板,并请求与启动有关的信息。 该面板称为启动配置选项卡组 。 图1的右侧显示了一个示例选项卡组。该选项卡组由多个选项卡组成,图1中的可见选项卡接受要调试的可执行文件及其项目的名称。
每次启动都必须具有自己的选项卡组,并且必须在plugin-in.xml中将其标识为org.eclipse.debug.ui.launchConfigurationTabGroups
的扩展。 清单2显示了此扩展在本示例中的外观。
此扩展很容易理解。 type
字段标识启动配置, class
标识创建选项卡组的类, id
为选项卡组提供唯一的名称。 由类标识的class
必须实现ILaunchConfigurationTabGroup
接口,其工作是创建一个或多个ILaunchConfigurationTab
。 这些选项卡为调试器提供了操作所需的信息,包括调试标志,源代码的位置和内存地址。 要配置ILaunchConfigurationTab
来完成其工作,您必须实现两个重要的方法:
createControl(Composite parent)
—为调试器选项卡创建用户界面 performApply(ILaunchConfigurationWorkingCopy configuration)
—配置调试器参数 第二种方法特别重要。 它通过为LaunchConfigurationWorkingCopy
属性分配值来LaunchConfigurationWorkingCopy
。 此数据对象包含调试所需的信息,并且在调试会话开始时将其发送到调试器。 属性名称在ICDTLaunchConfigurationConstants
接口中列出。 重要属性包括:
ATTR_DEBUGGER_ID
ATTR_DEBUGGER_SPECIFIC_ATTRS_MAP
ATTR_PROJECT_NAME
ATTR_PROGRAM_NAME
ATTR_PROGRAM_ARGUMENTS
ATTR_PLATFORM
ExampleConfigurationTabGroup
代码创建一个配置选项卡: ExampleTab
。 此选项卡显示六个预初始化的文本框-每个先前详述的属性。 图2显示了ExampleTab
外观。 通常,您应该创建带有各种控件的多个选项卡。 CDT提供了用于配置C / C ++调试器的CDebuggerTab
类。
ExampleTab
的代码使用setDefaults()
方法初始化调试属性。 此方法将示例调试器标识为要使用的调试器,并搜索选定的CDT资源以查找要调试的项目和程序。 执行此搜索不需要新代码,因为ExampleConfigurationTab
扩展了CDT的CLaunchConfigurationTab
类。 这个抽象类提供了两个重要的方法: getContext()
返回CDT资源, initializeCProject()
使用项目名称初始化ATTR_PROJECT_NAME
属性。
当您单击Debug时 ,Eclipse将搜索ATTR_DEBUGGER_ID
属性标识的调试器。 在示例项目中,将其设置为org.dworks.debugexample.ExampleDebugger
,它与示例项目扩展名org.eclipse.cdt.debug.core.CDebugger
的id
字段相对应。 清单3展示了完整的扩展。
当调试器启动时,Eclipse将检查调试器的platform
和cpu
元素是否支持处理环境。 如果是这样,它将检查以确保调试器的mode
元素支持当前的启动模式。 如果所有检查均通过,则Eclipse将在class
字段中找到标识的class
。 此类必须实现ICDIDebugger2
接口,因此必须提供createSession()
方法的实现。
createSession()
的目标是构造一个实现ICDISession
接口的对象。 此对象使CDT可以在调试器运行时访问调试器。 此访问提供了许多方法,其中最重要的三个方法如下:
getSessionProcess()
—返回正在运行的调试器的进程 getTargets()
—返回要调试的目标数组 getEventManager()
—返回添加和删除事件侦听器的管理器对象 这些方法中的第一个很简单,并且返回与调试器可执行文件相对应的Process
对象。 接下来的两个方法getTargets()
和getEventManager()
涉及更多。 本文的其余部分将对它们进行解释。 因为这些方法取决于调试器可执行文件,并且由于示例插件没有插件,所以ExampleDebugger
类将这些方法ExampleDebugger
空。
当CDT调用getTargets()
,会话必须为正在调试的每个进程提供ICDITarget
。 ICDITarget
的工作是接收调试命令,将其转换为调试器,然后将其发送给调试器。 例如,当您单击CDT调试透视图中的“ 步骤”或“ 继续”按钮时,CDT分别调用目标的stepOver()
或resume()
方法。 CDI对调试器目标接口的工作方式没有任何要求,但是第2部分解释了gdb如何使用MI协议与目标接口。
除了将命令发送到调试器之外, ICDITarget
还将调试器的输出发送给任何有兴趣接收调试器的对象。 这是通过CDI事件完成的,这是会话的getEventManager()
方法所在的位置。当任何CDI对象(例如RegisterView
)希望收到调试器事件的通知时,它将调用getEventManager()
来访问会话的ICDIEventManager
。 然后,它调用管理器的addEventListener()
方法将自身添加为侦听器。 当调试器产生输出时,目标调用管理器以警告其所有侦听器。 管理器通过调用每个侦听器的handleDebugEvents()
方法来执行此操作,该方法必须由所有ICDIEventListener
实现。
CDI提供了一组标准的ICDIEvent
。 每个调试器的响应或调试环境中的更改必须打包为以下之一:
ICDIBreakpointMovedEvent
ICDIChangedEvent
ICDICreationEvent/ICDIDestroyedEvent
ICDIExitedEvent
ICDIRestartedEvent/ICDIDisconnectedEvent
ICDIExecutableReloadedEvent
ICDISuspendedEvent/ICDIRestartedEvent/ICDIResumedEvent
部分2点的细节的gdb输出是如何转化为MIEvent
S和如何MIEvent
小号成为ICDIEvent
秒。
ICDIChangedEvent
特别重要,因为每次目标更改时都会触发该事件。 目标的每个可变方面都由ICDIObject
表示,这些对象形成称为CDI模型的层次结构。 它们包括ICDIRegister
, ICDIVariable
, ICDIMemoryBlock
, ICDIThread
等等。 ICDITarget
是这些CDI模型对象的根和容器。 每个ICDIObject
必须实现的唯一方法是getTarget()
。
控制调试器的两种最重要的方法是使用断点和观察点。 一旦到达特定位置或满足条件,断点就会终止调试器。 当读取或写入特定变量时,监视点将停止调试器。 CDI提供了两个接口来表示这些接口: ICDIBreakpoint
及其子接口ICDIWatchpoint
。 ICDIBreakpoint
可以是常规的,临时的或硬件辅助的; ICDIWatchpoint
可以是读类型,写类型或两者都可以。
您可以通过ICDIBreakpointManagement
实例创建和删除断点和观察点。 这提供了许多相关方法,例如setLineBreakpoint()
, deleteBreakpoints()
和setWatchpoint()
。 但请务必记住, org.eclipse.debug.core
插件的插件类提供了自己的断点管理器IBreakpointManager
,您可以使用DebugPlugin.getDefault().getBreakpointManager()
。 在许多情况下,您可能需要访问它并将IBreakpoint
转换为ICDIBreakpoint
。
从头开始构建图形调试环境是一项艰巨的任务:不仅必须了解目标处理器的内外,而且还必须与调试器进行通信并将其输出传递给图形用户环境。 对于不是Hercules的用户,Eclipse提供了一个API,用于将自定义调试器添加到CDT框架。 该API称为C / C ++调试器接口(CDI),本文介绍了其操作和使用的基础知识。 本系列“ 与CDT调试器接口 ”的第2部分介绍了CDT如何使用CDI来连接所有最好的开源调试器:GNU调试器(gdb)。
翻译自: https://www.ibm.com/developerworks/opensource/library/os-eclipse-cdt-debug1/index.html
vsc++调试没有调试界面