c++ 14中未指定指针转换的行为

How does an unspecified pointer conversion behave in C++14?

本文关键字:转换 指针 未指定 c++      更新时间:2023-10-16

一些指针强制转换的结果被描述为未指定。例如,[expr.static.cast]/13:

类型为"指向cv1 void的指针"的右值可以转换为类型为"指向cv2 T的指针"的右值[…]如果原指针值表示内存中某个字节的地址A,且A满足T的对齐要求,则生成的指针值表示与原指针值相同的地址A。其他任何此类指针转换的结果均未指明

我的问题是:在对齐不满足的情况下,可能的结果是什么?

例如,允许以下结果吗?

  • 一个空指针
  • 无效的指针值(即指针不指向大小为T的已分配存储)
  • 指向T的有效指针,该指针位于完全独立的内存部分

参考代码示例:

#include <iostream>
int main(int argc, char **argv)
{
    int *b = (int *)"Hello, world";   // (1)
    *b = -1;                           // (2)
    std::cout << argc << 'n';
}

(1)行触发了我上面引用的[exp .static]。cast]/13,因为它是由[exp .reinterpret]覆盖的reinterpret_cast。cast]/7定义了从static_castvoid *的转换。

如果未指定的结果可能是一个无效的指针值,那么(1)行可能导致硬件trap。(参考:N4430,它澄清了c++ 14和c++ 11中的类似措辞)。

推论问题:是否存在1行会导致未定义行为的情况?(现阶段我不这么认为;因为c++ 14无效的指针值读取是实现定义的或导致硬件陷阱)。


同样有趣的是,(2)行在大多数情况下都是未定义的行为,因为严格的混叠违反(也许还有其他原因),但是如果未指定的结果可能是&argc,那么这个程序可以输出-1而不触发未定义的行为!

我的问题是:在对齐不满意的情况下,可能的结果是什么?

据我所知,N4303:指针安全和位置new部分地回答了这个问题,尽管有些间接。本文参考了CWG第1412期:指定指针转换时的问题,该问题导致了[expr.static]的更改。Cast]/13,你引用,特别添加:

[…[…]

如果原指针值表示内存中某个字节的地址A,且A满足T的对齐要求,则生成的指针值表示与原指针值相同的地址,即A,其他任何此类指针转换的结果都不确定。

关于这个变化,N4303说(强调mine):

在采用DR 1412 [CWG1412]的决议之前,bp的值在初始化时是未指定的,随后通过new-expression传递给operator new。该指针可能为空、未充分对齐或有其他使用危险。

因此,未指定的转换可能导致:

  • 空指针
  • 指针对齐不充分
  • 使用有危险的指针