【问题标题】:Is it possible to force an access violation when a specific address is accessed?访问特定地址时是否可以强制访问冲突?
【发布时间】:2010-08-05 02:58:32
【问题描述】:

我们有一个为对齐目的而过大的数组,这样一来错误就不会被通常的机制捕获。

是否可以在 Windows 中保护一个小的任意区域(数组开头和结尾的 16 个字节),从而导致访问冲突?语言是 C++。

【问题讨论】:

  • 检查请求的索引是否有效是不可能的?
  • 这是不可能的。可以保护的最小内存单元是一个页面,也就是 4K。从理论上讲,您可以对数据进行处理,使数组在页面边界处结束,但这似乎需要做很多工作,但收效甚微。
  • 您确定要访问冲突吗?异常处理会不会更容易?
  • @dreamlax:不幸的是,我们分发的是裸指针,所以没有检查索引。 @Luke:我认为可能是这种情况,我可能会使用在销毁时检查的哨兵/标签值。 @Martin York:例外就好,但我认为其余问题仍然适用。
  • @ngoozeff:我不确定我是否理解。你正在分发一个指向数组中元素的指针,而这个指针的接收者手动递增它?

标签: c++ windows memory-management


【解决方案1】:

我相信在 x86 架构中,将内存标记为受保护的最精细粒度是针对页面(我认为是 4K)。您可以设置数组,使开头或结尾落在页面边界上(并保护该页面)。但是让两端都落在这样的边界上当然需要一个非常具体的数组长度。

Here is 一个如何设置保护页面的示例。

【讨论】:

    【解决方案2】:

    您可以在 UNIX 操作系统上使用 __attribute__((aligned (PAGESIZE)))mprotect 的组合来执行此操作。在Windows上,我认为有一个相当于mprotect,但也仅限于一页内存。

    无法以更精细的粒度保护事物的原因是内存访问是由硬件而不是软件完成的。如果每一次内存访问都需要通过一些数据结构来检查页面是否受到保护,那将会非常慢。

    【讨论】:

      【解决方案3】:

      不直接。您可以做的最接近的是在这些缓冲区上设置数据断点。但是,x86 总共有 4 个这样的断点,它们最多 8 个字节。此外,您需要在 ring 0(内核模式)来设置它们。

      【讨论】:

      • SetThreadContext 可以为您完成内核模式部分的工作。可以在morearty.com/code/breakpoint 上找到显示如何操作的资源(您在其他限制方面是正确的)。
      • 实际上,它的 MSDN 页面明确指出“无法指定的 CONTEXT 结构中的某些值被静默设置为正确的值。这包括......调试寄存器中的全局启用位...... ”。据推测,并非所有 Windows 版本都像 YMMV 一样严格。
      【解决方案4】:

      我不认为这是可以做到的。你总是可以自己抛出异常。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-12-26
        • 1970-01-01
        • 2014-12-31
        • 1970-01-01
        • 2011-01-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多