C 故意浪费所有主内存来学习碎片

C 故意浪费所有主内存来学习碎片,c,memory,heap-fragmentation,C,Memory,Heap Fragmentation,在我的课堂上,我们有一个作业,其中一个问题是: C语言中的内存碎片:设计、实现并运行一个C程序,该程序执行以下操作:它为一系列3m数组分配内存,每个数组的大小为500000个元素;然后它取消分配所有偶数数组,并分配一个m数组序列,每个数组大小为700000个元素。测量程序分配第一个序列和第二个序列所需的时间量。选择m,以便耗尽程序可用的所有主内存。解释一下你的时间安排 我的执行情况如下: #include <iostream> #include <time.h> #inc

在我的课堂上,我们有一个作业,其中一个问题是:


C语言中的内存碎片:设计、实现并运行一个C程序,该程序执行以下操作:它为一系列3m数组分配内存,每个数组的大小为500000个元素;然后它取消分配所有偶数数组,并分配一个m数组序列,每个数组大小为700000个元素。测量程序分配第一个序列和第二个序列所需的时间量。选择m,以便耗尽程序可用的所有主内存。解释一下你的时间安排

我的执行情况如下:

#include <iostream>
#include <time.h>
#include <algorithm>

void main(){
    clock_t begin1, stop1, begin2, stop2;
    double tdif = 0, tdif2 = 0;
    for(int k=0;k<1000;k++){
    double dif, dif2;
    const int m = 50000;
    begin1 = clock();
    printf("Step One\n");
    int *container[3*m];
    for(int i=0;i<(3*m);i++)
    {
        int *tmpAry = (int *)malloc(500000*sizeof(int));
        container[i] = tmpAry;
    }
    stop1 = clock();
    printf("Step Two\n");
    for(int i=0;i<(3*m);i+=2)
    {
    free(container[i]);
    }
    begin2 = clock();
    printf("Step Three\n");
    int *container2[m];
    for(int i=0;i<m;i++)
    {
    int *tmpAry = (int *)malloc(700000*sizeof(int));
    container2[i] = tmpAry;
    }
    stop2 = clock();
    dif = (stop1 - begin1)/1000.00;
    dif2 = (stop2 - begin2)/1000.00;
    tdif+=dif;
    tdif/=2;
    tdif2+=dif2;
    tdif2/=2;
}
printf("To Allocate the first array it took: %.5f\n",tdif);
printf("To Allocate the second array it took: %.5f\n",tdif2);
system("pause");
};
#包括
#包括
#包括
void main(){
时钟从1开始,停止1,开始2,停止2;
双tdif=0,tdif2=0;
对于(intk=0;k许多libc实现(我认为包括glibc)在调用
free()时不会将内存释放回操作系统
,但保留它,以便在下一次分配时无需系统调用即可使用它。此外,由于现代分页和虚拟内存策略的复杂性,您永远无法确定物理内存中的任何内容,这使得有意对其进行分段几乎是不可能的(即使是分段的).你必须记住,所有的虚拟内存和物理内存都是不同的

(以下内容是为Linux编写的,但可能适用于Windows和OSX)

当您的程序进行第一次分配时,假设有足够的物理内存供操作系统压缩所有页面。它们在物理内存中不是相邻的,而是分散在任何可能的地方。然后操作系统修改页面表以生成一组连续的虚拟地址,这些地址引用分散的页面在内存中。但有一件事——因为你没有真正使用你分配的第一个内存,它成为了一个很好的交换对象。因此,当你开始进行下一次分配时,内存不足的操作系统可能会交换一些页面来为新的页面腾出空间。因此,你实际上就是我测量磁盘速度和操作系统分页机制的效率——而不是碎片


请记住,一组连续的虚拟地址在实际操作中(甚至在内存中)几乎从来都不是物理上连续的。

“选择m以耗尽程序可用的所有主内存。”-在某些系统上,这实际上是相当困难的。在我打字时,我有2GB的主内存,但在32位Windows上的进程无论如何只能使用2GB的虚拟地址空间。如果我有3GB的主内存,一个进程不可能全部使用。不过,我不记得的是,是否所有32位进程都共享相同的2GB和其他内存r 1GB仅由操作系统和驱动程序使用,或者32位Windows是否能够在进程之间正确共享3GB。某些操作系统在实际写入主内存之前不会分配主内存,因此您的计时在碎片方面可能没有多大意义。它可能只是虚拟碎片。需要检查的其他事项:取决于您的操作系统和设置,您可能在
malloc
中达到
mmap
阈值。50000个元素刚好低于默认值
M_mmap_MAX
,如果您在32位Linux上,则块超过了
M_mmap_阈值
。如果您确实触发了
mmap
,而不是使用堆,则分配结束作为单独的映射,不要遭受碎片化。尽量减少块的大小。为什么在C程序中,你做的<代码>包含< /代码>?C不是C++。@格雷戈:<代码> MMAP>代码>如何避免碎片化?