安全派生指针值的示例
Example of safely derived pointer value
我使用N3797工作草案。
Section 5.7/1规定:
[…对于加法,两个操作数都必须为算术或非作用域枚举类型,或者一个操作数必须是指向对象的指针完全定义的对象类型,其他类型必须具有整型或无作用域枚举类型。
Ok。但是考虑一下3.7.4.3/3节中的规则:
—加法运算或位运算的结果,其中之一操作数是安全派生指针的整数表示形式值
P
,如果经过reinterpret_cast<void*>
转换的结果将比较等于可从中计算的安全派生指针reinterpret_cast<void*>(P)
.
也就是说,我们不能对指向void
的指针应用指针算术。你能提供一个反映3.7.4.3规则的例子吗?
类似的问题并没有提供一个合适的例子,因为这里指向void算术器的指针
3.7.4.3/3所说的是,如果你有一个"安全派生指针的整数表示",并对它进行数学运算,如果你可以单独使用指针算术和强制转换得到相同的结果,那么结果只是一个有效的"安全派生指针的整数表示"。
虽然不允许直接对void*
进行算术操作,但是有各种其他方法可以从void*
获得有效的指针。虽然我懒得用标准中的引号来支持每一步,但是下面的例子应该是有效的:
double arr[10];
double* P = &arr[0]; // safely derived pointer
intptr_t N = reinterpret_cast<intptr_t>(P); // valid integer repr
void* V = reinterpret_cast<void*>(P);
// Compute &a[1] from V
void* V2 = reinterpret_cast<void*>(
static_cast<char*>(V) + sizeof(double));
// Do the same with N
intptr_t N2 = N + sizeof(double);
assert(reinterpret_cast<void*>(N2) == V2);
- V2是一个安全派生的指针,可从
reinterpret_cast<void*>(P)
计算 - N2是加性或位操作的结果,其中一个操作数(N)是安全派生的指针值P的整数表示形式
由于V2和N2比较相等,因此N2也是"安全派生指针的整数表示"。
垃圾收集实现需要跟踪指针。在实践中,这通常是通过使用内存映射作为键来实现的,因此内存中在特定数字范围内的任何指针大小的单词都被视为真正的指针,这样可以防止包括给定地址值在内的分配块的垃圾收集。这种策略是不精确的,c++的目标是做得更好,同时也支持现有的GC程序。
与你的直觉相反,项目符号确实有效地启用了"void*
上的指针算术"。reinterpret_cast
从指针获得的整数(std::intptr_t
)也必须作为指针被跟踪,并且对象继续影响垃圾收集,即使它被加法或按位操作修改。
std::uintptr_t handle1 = reinterpret_cast< std::uintptr_t >( new foo );
std::uintptr_t handle2 = reinterpret_cast< std::uintptr_t >( new foo );
// handle1 and handle2 won't be collected, despite no pointer-type references.
std::uintptr_t diff = handle2 - handle1; // not a pointer
std::uintptr_t sum = handle1 + diff; // sum refers to handle2
handle2 = 0; // Invalidate original reference to handle2
// At this point, the second foo is still reachable via sum.
严格的指针安全性改善了现状,但是当满足规则的操作没有生成实际的指针表示时,误报仍然是可能的。例如,从标准文本中不清楚diff
是否可跟踪,因为它是使用两个安全派生操作数的差操作的结果,而不是仅使用一个安全派生操作数的加法操作。(无论是否有些无关紧要,假阳性无论如何都会发生。)
- 为什么使用 "this" 指针调用派生成员函数?
- 如何使用基类指针引用派生类成员
- 将派生指针分配给C 中的其他派生类型
- 如何通过派生指针调用基类中的模板成员函数
- 如何将带有恒定指针作为参数的模板的派生指针使用
- 无法返回包含派生指针的向量
- 如何创建派生指针类变量
- C++强制转换为派生指针或设计错误
- 无法从派生指针访问公共基成员
- C++发送派生指针作为参数
- 将专用基指针强制转换为专用于其他模板参数的派生指针("adding on"专用化)
- 在派生指针上显式调用基类析构函数时编译错误
- 安全派生指针值的示例
- 安全派生指针的整数表示形式
- c++多态克隆:如何从基指针获得派生指针
- 如果我将派生指针转换为基指针,这两个指针是否保证具有相同的值?
- 以任何方式将基指针强制转换为派生指针是否危险
- 将派生指针隐式强制转换为其相应基类的引用
- 当派生指针仅添加方法时,将基指针强制转换为派生指针的有效性
- c++转换指针到派生指针到基指针的例子