使用 malloc 的内存切片,通过切片一个大的 malloc'd 内存

Memory slice using malloc by slicing one big malloc'd memory

提问人:Programmer 提问时间:11/16/2023 最后编辑:chqrlieProgrammer 更新时间:11/17/2023 访问量:75

问:

考虑一个多次调用的应用程序。该应用程序总共分配了 1000 个字节。malloc()free()

我正在尝试编写一个代码,通过切片一个大的 malloc'd 内存然后释放它来减少 / 调用的数量:mallocfree

#include <stdio.h>
#include <stdlib.h>

struct A
{
    char *s;
    int data;
};

struct B
{
    float len;
    char net;
    int data[];
};

struct C
{
    float len;
    char net;
    int data[10];
    struct B *b;
}; 

int main() {
    int s =0;
    char *p = malloc(1000);
    char *mem = p;
    //Alocate for struct A from above pool
    struct A *a = (struct A *)p;
    p += sizeof(struct A);
    struct B *b = (struct B *)p ;
    p += sizeof(struct B) + sizeof(int) * 3; //data[0]..data[2]
    struct C *c = (struct C *)p;
    free(mem);
    return 0;
}

这是解决我问题的合法方法吗?我的代码或场景中是否存在任何缺陷,我遗漏了这些缺陷并可能导致问题?

c malloc 免费

评论

4赞 user207421 11/16/2023
这正是并且已经在做的事情。您是否有理由 (a) 认为您一开始就遇到了“问题”,并且 (b) 认为您可以做得比现在更好?malloc()free()malloc()/free()
3赞 user207421 11/16/2023
编写更多代码并不能解决现有代码中的问题。
3赞 Tom Karzes 11/16/2023
你的方法的另一个问题是你忽略了对齐。如果分配一个包含 5 个字符的字符数组,后跟一个双精度值,则很可能最终得到一个未对齐的双精度值指针。 保证任何返回指针都满足任何数据类型中最严格的对齐要求。您的代码可能也应该这样做,除非您对支持的大小和对齐方式施加自己的限制。malloc
3赞 user694733 11/16/2023
不应在嵌入式系统中使用动态内存分配,因为它们通常必须长时间运行且独立,并且动态内存分配会带来许多不可预测性。请改用静态预分配。
3赞 Lundin 11/16/2023
为什么我不应该在嵌入式系统中使用动态内存分配?

答:

2赞 Serge Ballesta 11/16/2023 #1

您很有可能只是添加新的错误源......

虽然电平相当低,但 - 对旨在避免对齐问题。如果要重新实现它,这将是要考虑的第一个问题。mallocfree

接下来的错误在内存地址计算中很容易。

这些行似乎没问题:

char *p = malloc(1000);          // ok char pointer on newly allocated memory
char *mem = p;                   // id.

struct A* a = (struct A*)p;      // ok as you are at the start of the malloc'ed block
p += sizeof(struct A);           // ok, p now points just past a

p += sizeof(struct B) + sizeof(int) * 3;  // ok,if there is no alignment problem (1)

free(mem);                                // ok, you release the full bloc

(1) 实际上为数组数据大小为 3 的 B 结构保留了一些内存,前提是 p 最初为 B 结构正确对齐

这个似乎更成问题:

struct B* b = (struct A*)p + sizeof(int) * 3;//data[0]..data[2] ???

(struct A*)p将指针指向 。如果向其添加整数值,则会将其视为指向 数组 的初始元素的指针。所以会跳过,这意味着 6、12 或 24,具体取决于 int 大小,结构体 A 大小的元素struct Astruct Ab3*sizeof(int)

此代码提示您可以让一些错误潜入您的新库。你确定你真的会相信它吗?

评论

0赞 Programmer 11/16/2023
这实际上是一个错别字错误,它会是这样的 - struct B *b = (struct B *)p ;p += sizeof(结构体 B) + sizeof(int) * 3;数据[0]..数据[2]
2赞 Useless 11/16/2023 #2

听起来你要找的是一个竞技场分配器,在某些情况下,这是一种完全正常的技术。

一旦你解决了对齐问题,并将你的代码组织成一个深思熟虑的、独立的领域,你会发现

  • 它不能修复或轻松处理碎片。因此,根据分配模式,最终可能会使用更多内存

  • 它不会使将分配与解除分配正确匹配变得更容易(或更难)

  • 它确实允许您一次性释放(或重置)整个竞技场,因此任何丢失的释放分配都不会造成永久性泄漏。

    (它们仍然是暂时的泄漏,因为它们增加了重置之间竞技场上的压力和碎片)

有时,在重置之前根本不担心释放是有道理的。这回避了前两点,但它是否可接受完全取决于您的分配模式(以及您可以承受多少内存浪费)。

知道了技术的名称,应该很容易找到工作示例。