gpt4 book ai didi

c++ - 动态分配正确对齐的内存 : is the new-expression on char arrays suitable?

转载 作者:太空狗 更新时间:2023-10-29 23:03:13 25 4
gpt4 key购买 nike

我遵循 Stefanus Du Toit 的沙漏模式,即用 C++ 实现 C API,然后再次用 C++ 包装它。这与 pimpl 习语非常相似,它对用户也是透明的,但可以防止更多与 ABI 相关的问题,并允许更广泛的外语绑定(bind)。

指向实现的指针方法一样,底层对象的大小和布局在编译时不为外界所知,因此它所在的内存必须动态分配( mostly)。然而,与 pimpl 的情况不同,对象已在分配点被完全定义,这里它的属性完全隐藏在一个不透明的指针后面。

使用 std::malloc 获得的内存是“适合任何标量类型对齐”,这使得它不适合该任务。我不确定 new-expression .引用自 Allocation 部分链接页面的:

In addition, if the new-expression is used to allocate an array of char or an array unsigned char, it may request additional memory from the allocation function if necessary to guarantee correct alignment of objects of all types no larger than the requested array size, if one is later placed into the allocated array.

这是否意味着以下代码是合规的?

C API

size_t object_size      ( void );     // return sizeof(internal_object);
size_t object_alignment ( void ); // return alignof(internal_object);
void object_construct ( void * p ); // new (p) internal_object();
void object_destruct ( void * p ); // static_cast<internal_object *>(p)->~internal_object();

C++ 包装器

/* The memory block that p points to is correctly aligned
for objects of all types no larger than object_size() */
auto p = new char[ object_size() ];
object_construct( p );
object_destruct( p );
delete[] p;

如果不是,如何动态分配正确对齐的内存?

最佳答案

我找不到标准保证您提议的代码工作的地方。首先,我找不到支持您从 CppReference.com 引用的内容的标准部分,但即使我们相信该声明,它仍然只是说它可以分配额外的空间。否则,您就完蛋了。

标准确实说明了operator new[]返回的内存对齐方式:“返回的指针应适当对齐,以便它可以转换为指针任何完整的对象类型……” (C++03,§3.7.2.1/2;C++11,§3.7.4.1/2)但是,在您计划分配内存的上下文中,您计划存储在其中的类型不是t 一个完整的类型。此外,operator new[] 的结果不一定与 new 表达式 new char[…] 的结果相同;后者被允许为其自己的数组簿记分配额外的空间。

您可以使用 C++11 的 std::align。为了保证您分配的空间可以对齐到所需的数量,您必须分配 object_size() + object_alignment() - 1 字节,但实际上,仅分配 object_size() 字节可能没问题。因此,您可以尝试像这样使用 std::align:

size_t buffer_size = object_size();
void* p = operator new(buffer_size);
void* original_p = p;
if (!std::align(object_alignment(), object_size(), p, buffer_size) {
// Allocating the minimum wasn't enough. Allocate more and try again.
operator delete(p);
buffer_size = object_size() + object_alignment() - 1;
p = operator new(buffer_size);
original_p = p;
if (!std::align(object_alignment(), object_size(), p, buffer_size)) {
// still failed. invoke error-handler
operator delete(p);
}
}
object_construct(p);
object_destruct(p);
operator delete(original_p);

allocator described in another question完成同样的事情。它是根据正在分配的对象的类型模板化的,您无权访问,但不需要那样做。它唯一一次使用其模板类型参数是评估 sizeofalignof,您已经从 object_sizeobject_alignment 函数。

这似乎对图书馆的消费者提出了很多要求。如果您将分配也移到 API 后面,对他们来说会方便得多:

void* object_construct() {
return new internal_object();
}

确保通过调用 delete 也移动析构函数,而不仅仅是析构函数。

这使得任何对齐问题都消失了,因为真正需要知道它的唯一模块是已经知道有关正在分配的类型的所有其他信息的模块。

关于c++ - 动态分配正确对齐的内存 : is the new-expression on char arrays suitable?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26471718/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com