检查子对象的地址是否在包含对象的边界内是否合法 [英] Is it legal to check whether the address of a subobject lies within the bounds of a containing object

查看:78
本文介绍了检查子对象的地址是否在包含对象的边界内是否合法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

2个问题:

  1. 以下代码是否具有定义好的行为?

  1. Is the following code well formed with defined behaviour?

有没有可能在其中声明的c ++实现?

Is there any possible c++ implementation in which it could assert?

代码(c ++ 11及更高版本):

Code (c++11 and higher):

#include <cassert>
#include <utility>
#include <ciso646>

template<class T> 
auto to_address(T* p) { return reinterpret_cast<unsigned char const*>(p); }

/// Test whether part is a sub-object of object
template<class Object, class Part>
bool is_within_object(Object& object, Part& part)
{
    auto first = to_address(std::addressof(object)),
                 last = first + sizeof(Object);

    auto p = to_address(std::addressof(part));

    return (first <= p) and (p < last);
}

struct X
{
    int a = 0;

    int& get_a() { return a; }
    int& get_b() { return b; }
private:

    int b = 0;
};

int main()
{
    X x;

    assert(is_within_object(x, x.get_a()));
    assert(is_within_object(x, x.get_b()));
}

请注意,ab具有不同的访问说明.

Note that a and b have different access specifiers.

推荐答案

指针比较在

比较对象的不相等指针的定义如下:

Comparing unequal pointers to objects is defined as follows:

  • 如果两个指针指向同一数组的不同元素或其子对象,则下标较高的元素的指针比较大.
  • 如果两个指针递归地指向同一对象的不同非静态数据成员或此类对象的子对象,则如果两个成员具有相同的访问控制并提供其类,则指向后来声明的成员的指针比较大不是工会.
  • 否则,两个指针的比较都不会大于另一个.
  • If two pointers point to different elements of the same array, or to subobjects thereof, the pointer to the element with the higher subscript compares greater.
  • If two pointers point to different non-static data members of the same object, or to subobjects of such members, recursively, the pointer to the later declared member compares greater provided the two members have the same access control and provided their class is not a union.
  • Otherwise, neither pointer compares greater than the other.

如果两个操作数p和q比较相等,则p <= q和p> = q都为true,而pq都为false.否则,如果指针p比较大于指针q,则p> = q,p> q,q <= p和q = p,并且q> p均得出false.否则,未指定每个运算符的结果.

If two operands p and q compare equal, p<=q and p>=q both yield true and pq both yield false. Otherwise, if a pointer p compares greater than a pointer q, p>=q, p>q, q<=p, and q=p, and q>p all yield false. Otherwise, the result of each of the operators is unspecified.

我们可以从中得出什么结论?

What conclusions can we draw from this?

在一个对象中,相同类型的指针的总顺序,但是对于具有不同访问控制的不同对象或不同子对象的指针,没有顺序 .缺少一般的总体指针顺序使is_within_object()变得没有意义.在您期望它返回true的情况下,它可以工作.在您希望它返回false的情况下,这些运算符的结果是不确定的吗?这不是一个非常有用的结果.

There is a total order of pointers of the same type within an object, but there is no order of pointers to different objects or of different subobjects with different access control. This lack of a general total order of pointers makes is_within_object() not very meaningful. In the cases where you'd expect it to return true, it works. In the cases where you'd expect it to return false, the result of these operators is unspecified? That's not a very useful result.

那个说,我们确实存在一个巨大的漏洞,形式为

That said, we do have a giant loophole for this in the form of [comparisons]:

对于模板lessgreaterless_­equalgreater_­equal,任何指针类型的专业化都产生严格的总顺序,这些顺序在这些专业化之间是一致的,并且还与内置运算符<><=>=.

For templates less, greater, less_­equal, and greater_­equal, the specializations for any pointer type yield a strict total order that is consistent among those specializations and is also consistent with the partial order imposed by the built-in operators <, >, <=, >=.

因此以下内容将得到明确定义:

So the following would be well-defined:

template<class T> 
auto byte_address(T& p) {
    return reinterpret_cast<std::byte const*>(std::addressof(p));
}

template<class Object, class Part>
bool is_within_object(Object& object, Part& part)
{
    auto first = byte_address(object);
    auto last = first + sizeof(Object);   
    auto p = byte_address(part);


    return std::less_equal<std::byte*>{}(first, p) &&
        std::less<std::byte*>{}(p, last);
}

这篇关于检查子对象的地址是否在包含对象的边界内是否合法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆