为什么数据断点在未对齐的地址上不起作用

ama*_*ang 5 c++ debugging breakpoints visual-c++

在Visual Studio中调试C ++项目时,某些数据断点永远不会命中。

所以我写了一些测试代码:

#include <iostream>
#include <stdint.h>

void test(uint32_t* p)
{
    *p = 0;

    // set a data breakpoint on p

    *((char*)p + 2) = 0x1;

    std::cout << *p << std::endl;
}

uint32_t* alloc(size_t offset)
{
    char* p = new char[sizeof(uint32_t) + offset];
    p = p + offset;
    return (uint32_t*)p;
}

int main()
{
    test(alloc(0));    // test #1
    test(alloc(2));    // test #2
}
Run Code Online (Sandbox Code Playgroud)

如您所见,在功能测试中,* p的值将首先置零,然后将其隐式更改,我得到了一个小端CPU,因此必须为65536。

如果在p(4个字节)上设置数据断点以检测更改,则会得到两个不同的结果:是否命中。它取决于所指向的p的地址。

在我上面的测试代码中,测试#1将命中,而测试#2将不命中,#1和#2之间的区别是alloc(0)和alloc(2)返回的地址。

本文如何:在MSDN上设置数据断点不会讨论此问题。

数据断点不能在未对齐的地址上工作吗?

Mat*_*lia 5

数据断点是在CPU的帮助下,通过x86上的调试寄存器设置的。关于它们,英特尔手册说(第17.2.5节):

断点地址寄存器(DR0通过调试寄存器DR3)和LENn每个断点的字段定义了数据或I / O断点的顺序字节地址范围。这些LENn字段允许指定1、2、4或8字节范围,从相应调试寄存器(DRn)中指定的线性地址开始。两字节范围必须在字边界上对齐;4字节范围必须在双字边界上对齐。I / O地址为零扩展(从16到32位,用于与所选调试寄存器中的断点地址进行比较)。这些要求由处理器执行。它使用LENn字段位来掩盖调试寄存器中的低位地址。未对齐的数据或I / O断点地址不会产生有效的结果。

(添加了重点)

因此,限制在于硬件。