绑定断点
如果用户通过按 F9 设置断点,IDE 会制定请求并提示调试会话创建断点。
设置断点
设置断点是一个双重过程,因为受断点影响的代码或数据可能尚不可用。 首先,必须描述断点,然后,当代码或数据变为可用时,它必须绑定到该代码或数据,如下所示:
断点是从相关的调试引擎(DEs)请求的,然后断点绑定到代码或数据,因为它变得可用。
断点请求将发送到调试会话,该会话将其发送到所有相关的 DES。 选择处理断点的任何 DE 都创建相应的挂起断点。
调试会话收集挂起的断点,并将其发送回调试包(Visual Studio 的调试组件)。
调试包会提示调试会话将挂起的断点绑定到代码或数据。 调试会话将此请求发送到所有相关的 DES。
如果 DE 能够绑定断点,它将断点绑定事件发送回调试会话。 否则,它会改为发送断点错误事件。
挂起断点
挂起的断点可以绑定到多个代码位置。 例如,C++ 模板的源代码行可以绑定到从模板生成的每个代码序列。 调试会话可以使用断点绑定事件来枚举在发送事件时绑定到断点的代码上下文。 以后可以绑定更多代码上下文,因此 DE 可能会为每个绑定请求发送多个断点绑定事件。 但是,DE 应为每个绑定请求仅发送一个断点错误事件。
实现
以编程方式,调试包调用会话调试管理器(SDM),并为它提供一个 IDebugBreakpointRequest2 接口,该接口包装了一个 BP_REQUEST_INFO 结构,其中描述了要设置的断点。 尽管断点可以是多种形式,但它们最终解析为代码或数据上下文。
SDM 通过调用其 CreatePendingBreakpoint 方法将此调用传递给每个相关的 DE。 如果 DE 选择处理断点,它将创建并返回 IDebugPendingBreakpoint2 接口。 SDM 收集这些接口,并将其作为单个 IDebugPendingBreakpoint2
接口传回调试包。
到目前为止,尚未生成任何事件。
然后,调试包通过调用 DE 实现的 Bind 来尝试将挂起的断点绑定到代码或数据。
如果断点已绑定,DE 会将 IDebugBreakpointBoundEvent2 事件接口发送到调试包。 调试包使用此接口通过调用 EnumBoundBreakpoints 来枚举绑定到断点的所有代码上下文(或单个数据上下文),后者返回一个或多个 IDebugBoundBreakpoint2 接口。 GetBreakpointResolution 接口返回 IDebugBreakpointResolution2 接口,GetResolutionInfo 返回包含代码或数据上下文的BP_RESOLUTION_INFO联合。
如果 DE 无法绑定断点,它将单个 IDebugBreakpointErrorEvent2 事件接口发送到调试包。 调试包通过调用 GetErrorBreakpoint 检索错误类型(错误或警告)和信息性消息,后跟 GetBreakpointResolution 和 GetResolutionInfo。 这会返回包含 错误类型和消息的BP_ERROR_RESOLUTION_INFO 结构。
如果 DE 处理断点但无法绑定断点,则返回类型 BPET_TYPE_ERROR
错误。 调试包通过显示错误对话框进行响应,IDE 在源代码行左侧的断点字形中放置感叹号标志符号。
如果 DE 处理断点,无法绑定断点,但其他一些 DE 可能会绑定它,它将返回警告。 IDE 通过在源代码行左侧的断点字形中放置问题标志符号来做出响应。