使用std :: launder获取指向活动对象成员的指针,从指向非活动对象的指针? [英] Using std::launder to get a pointer to an active object member from a pointer to an inactive object?

查看:55
本文介绍了使用std :: launder获取指向活动对象成员的指针,从指向非活动对象的指针?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此问题遵循以下 one

让我们考虑以下示例代码:

Let's consider this example code:

struct sso
  {
  union{
    struct {
      char* ptr;
      char size_r[8];
      } large_str;
    char short_str[16];
    };

  bool is_short_str() const{
    return *std::launder(short_str+15)=='\0'; //UB?
    }
  };

如果short_str不是活动成员,则取消引用没有std::launder的指针将是UB.让我们考虑一下ABI的详细说明,并且我们知道size_r [7]与short_str [15]位于相同的地址.当short_str不是联合的活动成员时,std::launder(short_str+15)是否返回指向size_r[7]的指针?

If short_str is not the active member dereferencing the pointer without std::launder would be UB. Let's consider that the ABI is well specified and that we know that size_r[7] is at the same address as short_str[15]. Does std::launder(short_str+15) return a pointer to size_r[7] when short_str is not the active member of the union?

Nota:我认为是这种情况,因为 [ptr.launder] /3

Nota: I think this is the case because [ptr.launder]/3

通过一个指向对象Y的指针值可以到达一个存储字节,如果该对象位于Y所占用的存储空间内,则该对象可以与Y进行指针可互转换,或者如果Y是一个数组元素.

A byte of storage is reachable through a pointer value that points to an object Y if it is within the storage occupied by Y, an object that is pointer-interconvertible with Y, or the immediately-enclosing array object if Y is an array element.

推荐答案

让我们考虑一下ABI的详细规定,我们知道size_r [7]与short_str [15]位于相同的地址

Let's consider that the ABI is well specified and that we know that size_r[7] is at the same address as short_str[15]

这完全取决于保证的确切含义.

It depends entirely on what that guarantee means exactly.

编译器可以自由保证

Sso.short_str[15]

可以访问和修改

,甚至在Sso.large_str当前处于活动状态时,也可以进行所有操作,并且可以准确地获取您期望的语义.

can be accessed and modified and everything even when Sso.large_str is currently active, and get exactly the semantics you expect.

或者不给予任何保证是免费的.

Or it is free not to give that guarantee.

对格式错误或表现出不确定行为的行为或程序没有任何限制.

There is no restriction on the behavior or programs that are ill-formed or exhibit undefined behavior.

因为那里没有对象,所以&Sso.short_str[15]不能与任何对象进行指针互换.一个不存在的对象没有另一个对象的相同地址".

As there is no object there, &Sso.short_str[15] isn't pointer-interconvertible with anything. An object that isn't there doesn't have the "same address" as another object.

流水是根据指向预先存在的对象的指针定义的.然后销毁该指针,并创建一个具有相同地址的新对象(定义明确). std::launder然后允许您将指针指向不再存在的对象,并获取指向现有对象的指针.

Launder is defined in terms of a pointer to a pre-existing object. That pointer is then destroyed, and a new object with the same address is created (which is well defined). std::launder then lets you take the pointer to the object that no longer exists and get a pointer to the existing object.

您正在做的不是那样.如果使用&short_str[15]时使用 ,则将有一个指向对象的指针.而且ABI可以说这是与size_r[7]相同的地址.现在std::launder将在有效范围之内.

What you are doing is not that. If you took &short_str[15] when it was engaged, you'd have a pointer to an object. And the ABI could say that this was at the same address as size_r[7]. And now std::launder would be in the domain of validity.

但是编译器可以走得更远,并定义short_str[15]引用与size_r[7]相同的对象,即使它不处于活动状态.

But the compiler could just go a step further and define that short_str[15] refers to the same object as size_r[7] even if it isn't active.

最弱的ABI保证我只能看到short_str[15]处于活动状态时才能看到与您的内容一致;稍后,您将使用large_str,然后可以从&short_str[15]洗涤到&size_r[7].与您的陈述相一致的最强ABI保证使得不需要调用std::launder.在中间的某个位置std::launder是必需的.

The weakest ABI guarantee that I could see being consistent with your stuff would only work if you took the address of short_str[15] when it was active; later, you would engage the large_str, and then you could launder from &short_str[15] to &size_r[7]. The strongest ABI guarantee that is consistent with your statement makes the call to std::launder not required. Somewhere in the middle std::launder would be required.

这篇关于使用std :: launder获取指向活动对象成员的指针,从指向非活动对象的指针?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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