C 联合如何防止内存碎片?

C 联合如何防止内存碎片?,c,memory,C,Memory,我正在经历这个过程并学习C。页面上有趣的部分: 联合的真正目的是通过为内存中的数据安排一个标准大小来防止内存碎片。通过有一个标准的数据大小,我们可以保证当动态分配的内存被释放时留下的任何漏洞都会被相同类型的联合的另一个实例重用 我通过以下代码理解此部分: typedef struct{ char name[100]; int age; int rollno; }student; typedef union{ student *studentPtr;

我正在经历这个过程并学习C。页面上有趣的部分:

联合的真正目的是通过为内存中的数据安排一个标准大小来防止内存碎片。通过有一个标准的数据大小,我们可以保证当动态分配的内存被释放时留下的任何漏洞都会被相同类型的联合的另一个实例重用

我通过以下代码理解此部分:

typedef struct{
    char name[100];
    int age;
    int rollno;
  }student;

typedef union{
     student *studentPtr;
     char *text;
  }typeUnion;

int 
main(int argc, char **argv)
{
  typeUnion union1;

  //use union1.studentPtr

  union1.text="Welcome to StackOverflow";
  //use union1.text

  return 0;
}
嗯,在上面的代码中,union1.text正在重用union1.studentPtr以前使用的空间,虽然不完全,但仍在使用

现在,我不明白的是,
malloc
的空闲空间何时不能使用,从而导致内存碎片


编辑:浏览评论和答案时,必须使用,将此编辑添加到帖子中,假定它将帮助像我这样的初学者

一般来说,评论对工会有更多的专业知识

关于你的问题,我的理解是:

  • union
    为union变量中最大的数据类型留出内存。例如,在联合体中有一个
    short int
    和一个
    long int
    将为
    long int
    留出足够的内存

  • 想象一下,您声明的不是union而是
    short int
    变量。 但随后需要使用
    长int
    。因此,在
    short int
    然后使用
    malloc
    为长int分配内存。这必须是连续的记忆。现在你的记忆是这样的。 在另一块内存块中间有一个空闲字节。坐在那里等着你请求1字节的内存


旁白:如果你正在学习
c
我推荐。它已经过时了,但我喜欢简洁、清晰和教科书式的方法。

页面是错误的,大多数程序只是假设内存使用会很好,而不去注意它

在下图中,假设每个字符代表8个字节。字母表示不同的分配,下划线表示可用内存。所涉及的规模小得可笑,我跳过了细节(比如大多数malloc实现使用的分配元数据),但原则应该在那里

从空内存开始

_____________________________________________________
然后,在程序运行时会发生一系列32字节的分配

AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLL________
程序分配的内存一直扩展到超过“L”分配的最后一个字节,它使用12*8*4=384字节

现在,该计划将释放所有其他分配

AAAA____CCCC____EEEE____GGGG____IIII____KKKK__________
现在程序实际上只使用了6*4*8=192字节,但操作系统必须保留从分配给程序的第一个“A”到最后一个“K”的所有352字节。所有分配之间释放的间隙就是内存碎片的一个例子

现在程序想要分配另一个32字节的块。可能会发生这样的情况:

AAAAMMMMCCCC____EEEE____GGGG____IIII____KKKK_________
新的分配适合由空闲创建的一个间隙,这很好,因为它回收了一个间隙,所以我们浪费的空间更少

现在假设程序需要分配一个40字节的块。没有一个间隙足够大,因此分配必须在最后进行,操作系统必须为程序分配更多内存,352+40=392字节。这些间隙中的所有内存都被浪费了。这就是网页所说的内存碎片造成的浪费


如果一开始所有的分配都是40字节,那么间隙回收就可以最大化。

旁注:我强烈不同意作者关于“工会的真正目的”的观点,因为a)你必须只使用这些工会,才能有机会防止碎片化(即使这样,也无法保证),b)你很可能浪费了大量的内存,这比碎片化还要糟糕。@Siguza:事实上这是肯定的。但是,正如您所写的那样,您必须将所有其他数据类型放入单个
联合中。这完全违背了现代编码原则,即模块化。最初的陈述纯属无稽之谈!不同记录/联合/调用方式的原因是,单个数据类型包含不同类型的数据。这是允许数据元素变化的非OOPL方式。在C语言中,这也是将一种类型重新解释为另一种类型的唯一安全方法——初学者应该把手放在一边。你链接到的网站试图教授一种过时的C语言,推广过时的工具,通常情况下相当糟糕。我建议再也不要去那里了。我没有投反对票,但我不明白你的最后一句话,这似乎是你问题的关键。如果你只是问“内存碎片是如何发生的”,这与工会无关,并且可能在本网站上已经得到了回答。关于
经典文本
,请毫不拖延地订购本书,感谢您的建议