malloc 和 C 对齐:这种手工优化安全吗?
我放置了整个代码,但是当然,它位于不同的文件中(.h
和 .c
文件)
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 位对齐”。
我希望我说得足够清楚。
I put the whole code but, of course, it's in different files (.h
and .c
files)
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;
}
I am just wondering if this line of code: block->pieces = (&block + sizeof(Block));
will be always safe. I mean: can we be sure that, immediately after the sizeof(Piece)
, we will have precisely (sizeof(Piece) * nb_pieces)
? Are we sure there will never be an alignment problem (ie maybe if it's 64-bits aligned, the memory for sizeof(Block)
will be less than 8 bytes and the block->pieces
should not point to exactly sizeof(Block)
, but "sizeof(Block)
64 bits-aligned").
I hope I'm clear enough.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
首先,这并没有达到您的预期,并且有多种原因:
首先,
&block
是变量block
的地址,而不是的内容块
,并且类型为block **
。最多,您可以安全地为该指针值添加 1,因为更多的值将创建一个超出该变量末尾的指针,而该指针是无效的。因此,您需要将
&block
更改为block
。这仍然不会达到您的预期,因为指针算术会将原始地址增加对象大小的倍数。因此,添加sizeof(Block)
并不是向上移动 1 个数组元素,而是向上移动sizeof(Block)
数组元素。要解决此问题,您需要
block + 1
。现在您需要开始担心对齐问题。为了使Pieces
数组正确对齐,您需要检查_Alignof(Block)
和_Alignof(Piece)
是否相同。如果没有,您将需要添加填充字节:当然,您可以通过使
pieces
成员成为灵活数组成员来避免这一切:并且分配本身将是足够的。
First, this isn't doing what you expect, and for multiple reasons:
First,
&block
is the address of the variableblock
, not the contents ofblock
, and has typeblock **
. At most, you can safely add 1 this pointer value because anything more will create a pointer past the end of this variable which is invalid.So then you would need to change
&block
toblock
. That still won't do what you expect because pointer arithmetic increments the raw address by multiples of the object size. So addingsizeof(Block)
to this is not moving up 1 array element but moving upsizeof(Block)
array elements.To fix this you would need
block + 1
. Now you need to start worrying about alignment. For your array ofPieces
to be aligned properly, you would need to check if_Alignof(Block)
and_Alignof(Piece)
are the same. If not, you would need to add padding bytes:Of course, you can avoid all this by making the
pieces
member a flexible array member:And the allocation by itself will be enough.