c++ reinterpret_cast of pointer-to-pointer -是Undefined Behavior吗?

u5rb5r59  于 2023-10-20  发布在  其他
关注(0)|答案(1)|浏览(113)

我们需要将int**转换为void**,可以使用reinterpret_cast。然而,它在技术上是否被C++标准所允许,或者我们是否处于未定义行为的领域?

用例

使用Nvidia库时,我们需要使用指针到指针:

cudaMalloc(void** ptr, size_t size);

一个典型的解决方案是:

int* p;
cudaMalloc(reinterpret_cast<void**>(&p), 123);
niknxzdl

niknxzdl1#

强制转换本身是允许的,但在标准的保证下实际上并不有用,因为任何对结果的非平凡使用最终都会导致未定义的行为。
具体地说,如果alignof(void**) > alignof(int**),那么原始指针可能没有为void**适当地对齐,然后转换的结果将是未指定的,并且实际上任何对结果的使用都将导致未定义的行为。也就不可能转换回原始值。
否则,转换、传递指针和转换回int**都是允许的。但是,通过void**访问(例如,将指针值写入提供的指针到指针)将是一个别名冲突,因为void*不能别名int*。因此,如果cudaMalloc访问指针而没有首先转换回int**,则行为未定义。
这就是C++标准在这方面的全部内容。考虑到你似乎是专门询问CUDA,它的规范当然可以提供额外的保证。这在实践中可能会非常重要。
然而,如果你认为这是一个类似malloc的通用实现,那么就不可能编写这个函数来让这个使用模式定义行为,因为这个函数不知道它必须首先转换回哪个指针类型。这不仅仅是理论上的问题。许多编译器确实利用这种类型的UB来进行优化。
可以在没有混叠违规和UB的情况下实现的正确模式应该是这样的

void* p_temp;
cudaMalloc(&p_temp, 123);
auto p = static_cast<int*>(p_temp);

相关问题