STL
STL copied to clipboard
`<memory>`: Add different control block types for `allocate_shared_for_overwrite`
allocator_shared_for_overwrite creates allocated non-array objects by default-initialization, so these objects should be destroyed by plain destructor calls, not Ator::destroy. Currently the standard wording is unclear on make_shared_for_overwrite and allocate_shared_for_overwrite, so I submitted LWG-4024.
It's a bit unfortunate that the existing control block types can't be reused because the _Destroy functions can't recognize _For_overwrite_tag.
Unblocks one libcxx test:
std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared_for_overwrite.pass.cpp
Driven-by changes:
- completing visualizers of control blocks for array types.
Do these control blocks need new visualizers?
Do these control blocks need new visualizers?
I'm now trying to add visualizer for _Ref_count_obj_alloc_for_overwrite.
~But visualization of control block types for array types still seems missing and I have no idea how to handle them. Previous PRs #309, #1315, and the previous issue #2787 didn't mention these stuffs.~
Edit: Completed these visualizers. However, it's unfortunate that the control blocks for std::make_shared<TrivialType[]> can't be completely visualized since the size of array is not stored.
Test program
#include <memory>
#include <memory_resource>
#include <string>
int main() {
// make_shared for arrays of trivial types
{
auto p = std::make_shared<int[8]>();
p[1] = 42;
}
{
auto p = std::make_shared<int[]>(8);
p[1] = 42;
}
{
auto p = std::make_shared_for_overwrite<int[8]>();
p[1] = 42;
}
{
auto p = std::make_shared_for_overwrite<int[]>(8);
p[1] = 42;
}
// make_shared for arrays of non-trivial types
{
auto p = std::make_shared<std::string[8]>("s");
p[1] = "42";
}
{
auto p = std::make_shared<std::string[]>(8, "s");
p[1] = "42";
}
{
auto p = std::make_shared_for_overwrite<std::string[8]>();
p[1] = "42";
}
{
auto p = std::make_shared_for_overwrite<std::string[]>(8);
p[1] = "42";
}
// allocate_shared(_for_overwrite)
{
auto p = std::allocate_shared<int[8]>(std::allocator<int>{});
p[1] = 42;
auto q = std::allocate_shared<int[8]>(std::pmr::polymorphic_allocator<int>{});
q[2] = -42;
}
{
auto p = std::allocate_shared<int[]>(std::allocator<int>{}, 8);
p[1] = 42;
auto q = std::allocate_shared<int[]>(std::pmr::polymorphic_allocator<int>{}, 8);
q[2] = -42;
}
{
auto p = std::allocate_shared_for_overwrite<int>(std::allocator<int>{});
*p = 42;
auto q = std::allocate_shared_for_overwrite<int>(std::pmr::polymorphic_allocator<int>{});
*q = -42;
}
{
auto p = std::allocate_shared_for_overwrite<int[8]>(std::allocator<int>{});
p[1] = 42;
auto q = std::allocate_shared_for_overwrite<int[8]>(std::pmr::polymorphic_allocator<int>{});
q[2] = -42;
}
{
auto p = std::allocate_shared_for_overwrite<int[]>(std::allocator<int>{}, 8);
p[1] = 42;
auto q = std::allocate_shared_for_overwrite<int[]>(std::pmr::polymorphic_allocator<int>{}, 8);
q[2] = -42;
}
}
Thanks! :heart_eyes_cat: This investigation, fix, and visualizers must have been a lot of work, I really appreciate it. I pushed a couple of tiny commits and I think this is ready to go.
I'm mirroring this to the MSVC-internal repo - please notify me if any further changes are pushed.
Thanks for destroying this bug! :lady_beetle: :boom: :joy_cat: