首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >malloc和c对齐:这种手工优化安全吗?

malloc和c对齐:这种手工优化安全吗?
EN

Stack Overflow用户
提问于 2022-03-12 16:25:23
回答 1查看 72关注 0票数 2

我把整个代码放在不同的文件中(.h.c文件)

代码语言:javascript
复制
typedef unsigned char ubyte;
typedef unsigned int uint;
#include<stdbool.h>

typedef struct Cube {
    ubyte n;
    ubyte e;
    ubyte s;
    ubyte w;
} Cube;

typedef struct Piece {
    Cube c;
    bool is_main;
    char offset_n;
    char offset_s;
} Piece;

typedef struct Block {
    ubyte total;
    Piece* pieces;
} Block;

Block *block_create(uint nb_pieces) {
    Block *block = malloc(sizeof(Block) + (sizeof(Piece) * nb_pieces));
    block->pieces = (Piece *) (&block + sizeof(Block));
    return block;
}

我只是想知道这一行代码:block->pieces = (&block + sizeof(Block));是否是,始终是安全的。我的意思是:我们能确定,在sizeof(Piece)之后,我们就会有精确的(sizeof(Piece) * nb_pieces)吗?我们确定永远不会出现对齐问题(即如果64位对齐,sizeof(Block)的内存将小于8字节,block->pieces不应该指向精确的sizeof(Block),而是"sizeof(Block) 64位对齐“)。

希望我说得够清楚。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-03-12 16:36:54

首先,这不是您所期望的,而且有多种原因:

代码语言:javascript
复制
block->pieces = (&block + sizeof(Block));

首先,&block是变量block的地址,而不是block的内容,并且具有block **类型。最多,您可以安全地添加1这个指针值,因为任何更多的指针都会在这个变量结束后创建一个指针,该指针无效。

因此,您需要将&block更改为block。这仍然不能达到预期的效果,因为指针算法会将原始地址增加到对象大小的倍数。因此,向其中添加sizeof(Block)并不是向上移动1个数组元素,而是向上移动sizeof(Block)数组元素。

要解决这个问题,您需要block + 1。现在你需要开始担心对齐了。要正确地对齐Pieces数组,需要检查_Alignof(Block)_Alignof(Piece)是否相同。如果没有,则需要添加填充字节:

代码语言:javascript
复制
int padding = 0;
if (_Alignof(Block) % _Alignof(Piece) != 0) {
    padding = _Alignof(Piece) - (_Alignof(Block) % _Alignof(Piece));
}
Block *block = malloc(sizeof(Block) + padding + (sizeof(Piece) * nb_pieces));
block->pieces = (Piece *)((char *)(block + 1) + padding);

当然,您可以通过使pieces成员成为一个灵活的数组成员来避免这一切。

代码语言:javascript
复制
typedef struct Block {
    ubyte total;
    Piece pieces[];
} Block;

而分配本身就足够了。

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

https://stackoverflow.com/questions/71451305

复制
相关文章

相似问题

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