c++ 14中未指定指针转换的行为
How does an unspecified pointer conversion behave in C++14?
一些指针强制转换的结果被描述为未指定。例如,[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_cast
到void *
的转换。
如果未指定的结果可能是一个无效的指针值,那么(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。该指针可能为空、未充分对齐或有其他使用危险。
因此,未指定的转换可能导致:
- 空指针
- 指针对齐不充分
- 使用有危险的指针
- 转换指针引用的字符串
- 无法向上转换指针到指针参数
- 混合转换指针和引用
- 堆栈对象的强制转换指针
- 基类到派生模板类的强制转换指针,而不知道类型
- 删除类型转换指针的最佳方法
- 管理到本机值类转换:强制转换指针是否安全?
- 转换指针类型
- 为什么函数不能正确强制转换指针(从基类到派生类)
- 当我们递增下面的类型转换指针时会发生什么?
- 类型强制转换指针构造函数调用
- 如何转换(指针向量)-->(指向指针数组的指针)
- 如何从类功能转换指针
- 在C++对象中:我应该使用父类强制转换指针,还是应该使用实际类本身进行强制转换
- Delphi中的类型转换指针添加
- C++分段错误(核心转储)错误 - 强制转换指针/将函数值返回到线程
- 以C++和运算符优先级键入指向数组成员的强制转换指针
- C++动态强制转换指针的内存清理
- 转换指针和引用的好处
- 在c++中转换指针