- changed status to resolved
`deserialize_into()` example contains undefined behavior
The 2022.3.0 spec contains this example for deserializing_iterator<T>::deserialize_into()
:
BigObject *ptr = /* ... */;
future<> = rpc( target_rank,
[](view<BigObject> item) {
auto storage =
new typename std::aligned_storage<sizeof(BigObject),
alignof(BigObject)>::type;
BigObject *ptr = item.begin().deserialize_into(storage);
/* consume the object */
delete ptr;
},
make_view(ptr, ptr+1));
@Amir Kamil has pointed out that this idiom technically contains undefined behavior, because it invokes a C++ new
expression with one type (creating an object of type std::aligned_storage<...>::type
) and the corresponding delete
expression uses a pointer of a different type (destroying an object of type BigObject
).
The relevant text from C++11 [expr.delete]: (emphasis added)
In the first alternative (delete object), the value of the operand of delete may be a null pointer value, a pointer to a non-array object created by a previous new-expression, or a pointer to a subobject (1.8) representing a base class of such an object (Clause 10) . If not, the behavior is undefined.
Where the "non-array object created by the previous new-expression" would be an std::aligned_storage<...>::type
object, which is not the same object type as BigObject
nor part of an inheritance hierachy with it (hence UB).
We are not aware of any implementation where this distinction causes a problem, but we should fix our example idiom (and test code modeled on it) to remove the UB.
Comments (1)
-
reporter - Log in to comment
Fixed in spec PR 88 merged at bf9a261