首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++放置新的类对齐(在SAMD21微控制器上)

C++放置新的类对齐(在SAMD21微控制器上)
EN

Stack Overflow用户
提问于 2021-09-23 09:33:37
回答 2查看 88关注 0票数 0

我正在开发一个运行在SAMD21微控制器上的应用程序。对于那些不熟悉SAMD21的人,它包含一个ARM Cortex-M0+处理器。我所使用的具体型号有32 kB的内存。我的应用程序运行到了32 kB的极限,所以我一直在优化内存使用的代码。

我一直在做的一个优化就是减少堆碎片。例如,我可能有这样一个场景:

代码语言:javascript
复制
A *my_obj = new A();
B *my_second_obj = new B();
delete A;
C *my_third_obj = new C();

在上面的示例中,当实例化my_third_obj时,内存分配程序可能尝试将其放置在my_obj最初使用的空位置中。但是,如果my_third_obj不适合这个位置,那么内存分配程序只需在堆的顶部分配更多的空间并移动堆指针。这将在my_obj所在的位置留下一个“漏洞”(稍后可能被其他对象填充),但这会创建堆碎片。

在我的特定应用程序中,我确定在任何时候我都只需要A、B或C类的一个活动实例。正因为如此,我正在考虑创建一个内存块,它保存了所有这些类的当前实例,并且简单地使内存块与最大的类一样大,这样它就可以容纳任何一个类。这将减少堆碎片,因为内存中总是有一个特定的位置,我将在其中分配这些特定的类。

下面是我所想的一个简单的例子:

代码语言:javascript
复制
uint32_t max_size = sizeof(A);
max_size = (sizeof(B) > max_size) ? sizeof(B) : max_size;
max_size = (sizeof(C) > max_size) ? sizeof(C) : max_size;
uint8_t *buffer = new uint8_t[max_size];

//Some time later in the program...
C *my_obj = new(buffer) C();

//Some time later in the program...
my_obj->~C();
my_obj = NULL;
memset(buffer, 0, sizeof(max_size));
B *my_other_obj = new(buffer) B();

在我以前编写的代码中,我从未真正使用过放置新的,但我认为它在我当前的情况下是有用的。这里我的主要问题是:考虑到我所描述的示例,是否需要以任何方式修改代码以处理对齐问题?类A、B和C都有不同的成员变量和不同的大小。这段代码只是“工作”,还是我需要做一些特殊的事情来处理内存对齐?

谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-09-23 10:38:39

,我需要以任何方式修改代码来处理对齐问题吗?

是。

,我需要做什么特殊的事情来处理内存对齐吗?

是。

uint8_t概念上表示一个8位的无符号整数。使用charunsigned char表示1字节。

无论如何,使用operator new与大小和对齐:

代码语言:javascript
复制
auto maxsize = max_of_3(sizeof(A), sizeof(B), sizeof(C)),
auto neededalign = std::align_val_t(max_of_3(alignof(A), alignof(B), alignof(C));
void *buffer = operator new(maxsize, neededalign);

或静态地:

代码语言:javascript
复制
std::aligned_storage<
    max_of_3(sizeof(A), sizeof(B), sizeof(C)),
    max_of_3(alignof(A), alignof(B), alignof(C))> buffer;
A *stuff = new(buffer.data) A;
票数 1
EN

Stack Overflow用户

发布于 2021-09-23 10:19:41

可以保证从malloc获得的缓冲区对于任何基本类型都正确对齐,但我不确定从new获得的指针是否正确,因此我更倾向于:

代码语言:javascript
复制
uint8_t *buffer = malloc(max_size);   // delete it later with free

但是,您甚至可以通过使用alignas构建自定义缓冲区来消除任何动态分配。

代码语言:javascript
复制
// only required for C++11, starting from C++14, std::max is constepr
constexpr size_t max3(size_t i, size_t j, size_t k) {
    uint32_t max_size = i;
    max_size = (i > j) ? i : j;
    max_size = (k > max_size) ? k : max_size;
    return max_size;
}

// declare a custom struct with required size and alignment
struct alignas(max3(alignof(A), alignof(B), alignof(C))) Buffer {
    char buffer[max3(alignof(A), alignof(B), alignof(C))];
};

// build a statically allocated buffer of correct size and alignment
Buffer buffer;

从那时起,您可以安全地在buffer中构造一个对象,当然,在重用内存之前可以解释地销毁它。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69297501

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档