断点如何在C ++代码中运行?在编译代码时,它们是否在某些汇编指令之间插入了特殊指令?或者还有其他的东西吗?此外,如何实现代码逐步执行?与断点相同......?
答案 0 :(得分:37)
这很大程度上取决于CPU和调试器。
例如,x86 CPU上可能的解决方案之一:
观察点可以以类似的方式实现,但是您可以将监视变量所在的内存页面设置为只读,或者进入无访问模式,而不是INT3,等待分段异常。
也可以使用跟踪模式完成单步调试。也可以通过根据调试数据将断点放在下一条指令上来逐步执行源代码行。
当你只是将地址加载到某个寄存器时,某些CPU也有硬件断点支持。
答案 1 :(得分:8)
根据technochakra.com上的this blog entry,你是对的:
软件断点通过在正在调试的程序中插入特殊指令来工作。英特尔平台上的这条特殊指令是“int 3”。执行时,它调用调试器的异常处理程序。
我不确定如何执行下一条指令的步骤。但是,文章继续补充:
出于实际原因,每当添加或删除断点时都要求重新编译是不明智的。调试器更改内存中可执行文件的加载图像,并在运行时插入“int 3”指令。
但是,这只会用于“运行到当前行选项”。
答案 2 :(得分:4)
单步执行是在(汇编程序)代码级而不是在C ++级实现的。调试器知道如何将C ++代码行映射到代码地址。
有不同的实现。有些CPU支持使用断点寄存器进行调试。当执行到达断点寄存器中的地址时,CPU将执行断点异常。
另一种方法是使用特殊指令对执行时的代码进行修补,最好是单字节指令。在x86系统中,通常是int 3。
第一种方法允许ROM中的断点,第二种方法允许同时有更多的断点。
答案 3 :(得分:1)
AFAIK所有调试器(对于任何编译语言)允许无限数量的断点使用替换指令的变体使用特殊值(如上所述)进行断点,并保留已放置这些值的位置列表。
当处理器尝试执行这些特殊值之一时,会引发异常,调试器捕获它并检查异常的地址是否在其断点列表中。 如果是,则调用调试器并为用户提供交互机会。 如果它不是,那么异常是由于程序从一开始就存在的,并且调试器允许异常“传递”到可能存在的任何错误处理程序。
另请注意,调试自修改代码可能会失败,因为调试器会暂时修改代码本身。 (当然,没有人会写自我修改,现在他们会吗?&gt ;; - )
由于这些原因,重要的是调试器有机会在终止调试会话之前删除它设置的所有断点。