gpt4 book ai didi

c - 分配太少的空间是否安全(如果你知道你不需要它)?

转载 作者:太空狗 更新时间:2023-10-29 16:36:21 26 4
gpt4 key购买 nike

所以 C99 支持常用的“灵活数组成员”hack 让我们可以制作 struct可以过度分配以满足我们的大小要求。我怀疑在大多数理智的实现中这样做是完全安全的,但是如果我们知道在某些情况下我们不需要 struct 的某些成员,那么在 C 中“分配不足”是否合法? ?

抽象示例

假设我有一个类型:

struct a {
bool data_is_x;
void * data;
size_t pos;
};

如果data_is_x , 然后是 data 的类型是一种需要使用 pos 的类型成员。否则,使用此 struct 的函数不需要 pos struct 的这个特定副本的成员.本质上,struct携带有关它是否有 pos 的信息成员(member),此信息不会在struct内更改的一生(除了邪恶的恶作剧,无论如何都会破坏任何东西)。可以安全地说:

struct a *a = malloc(data_is_x ? sizeof(struct a) : offsetof(struct a, pos));

这将为 pos 分配空间仅在需要时加入?或者它是否违反了使用对 struct 来说太小的施法空间的约束指针,即使您从不使用相关成员?

具体例子

我的真实用例有点复杂;它在这里主要是为了让您了解为什么我想这样做:

typedef struct {
size_t size;
void * data;
size_t pos;
} mylist;

mylist_create 的代码指定,对于 size > 0 , data是一组连续数据,即 size项目长(无论项目可能是什么),但对于 size == 0它是包含项的双向链表的当前节点。所有适用于 mylist 的函数s 将检查是否 size == 0 .如果是这样,他们会将数据作为链表处理,“当前”索引是任何节点data。指着。如果不是,他们会将数据作为数组处理,“当前”索引存储在 pos 中。 .

现在如果size == 0我们真的不需要 pos成员,但如果size > 0我们将。所以我的问题是,这样做是否合法:

mylist *list = malloc(size ? sizeof(mylist) : offsetof(mylist, pos));

如果我们保证(对未定义行为的惩罚),而size == 0 ,我们永远不会尝试(或需要)访问 pos成员?或者它是否在标准中的某个地方说,甚至考虑这样做是 UB?

最佳答案

malloc 本身根本不关心您为结构分配了多少内存,它是未定义的 block 外部内存的解引用。来自 C99 6.5.3.2 地址和间接运算符:

If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined.

并且,从7.20.3 内存管理函数,我们发现(我的斜体):

The pointer returned if the allocation succeeds is suitably aligned so that it may be assigned to a pointer to any type of object and then used to access such an object or an array of such objects in the space allocated (until the space is explicitly deallocated).

因此,您可以执行以下操作:

typedef struct { char ch[100]; } ch100;
ch100 *c = malloc (1);

而且,如果您只尝试使用 c->ch[0] 做任何事情,这是完全可以接受的。


对于您具体的具体示例,假设您关心的是存储空间,我不太确定自己会那么担心。如果您出于其他原因担心,请随时忽略这一点,特别是因为其中包含的假设不是标准强制要求的。

根据我的理解,你有一个结构:

typedef struct {
size_t size;
void * data;
size_t pos;
} mylist;

你只想使用 data 其中 size 是 0,同时使用 datapos 其中 size 大于 0。这排除了将 datapos 放在 union 中的使用。

大量的 malloc 实现会将您请求的空间四舍五入为 16 字节的倍数(或更大的 2 的幂),以缓解内存碎片问题。这当然不是标准要求的,但它很常见。

假设(例如)32 位指针和 size_t,您的 12 字节结构很可能会占用 16 字节的竞技场 header 和 16 字节的数据 block 。即使您只要求 8 个字节(即没有 pos),这个 block 仍然是 16 个字节。

如果你有 64 位指针和 size_t 类型,它可能会有所不同 - 24 字节有 pos 和 16 没有。

但即便如此,除非您分配很多这些结构,否则这可能不是问题。

关于c - 分配太少的空间是否安全(如果你知道你不需要它)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7356431/

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