C分配和内存开销

C分配和内存开销,c,memory,memory-management,C,Memory,Memory Management,抱歉,如果这是一个愚蠢的问题,但它一直有点困扰我很长时间 我想知道一些关于内存管理器如何知道内存正在使用的细节 想象一下,一台单芯片微型计算机有1024B的RAM,没有多少空闲空间 现在分配100个int——每个int都是4个字节,每个指针也都是4个字节(是的,8位一个芯片很可能有更小的指针,但是w/e) 你刚才用了800B内存的100整数?但更糟糕的是,分配系统必须以某种方式注意内存的malloc'd位置和空闲位置-200个额外字节什么的?还是一些小痕迹 如果这是真的,为什么C语言比汇编语

抱歉,如果这是一个愚蠢的问题,但它一直有点困扰我很长时间

我想知道一些关于内存管理器如何知道内存正在使用的细节

想象一下,一台单芯片微型计算机有1024B的RAM,没有多少空闲空间

现在分配100个int——每个int都是4个字节,每个指针也都是4个字节(是的,8位一个芯片很可能有更小的指针,但是w/e)

你刚才用了800B内存的100整数?但更糟糕的是,分配系统必须以某种方式注意内存的malloc'd位置和空闲位置-200个额外字节什么的?还是一些小痕迹


  • 如果这是真的,为什么C语言比汇编语言更受欢迎

  • 真的是这样吗?那么超低效

  • (或者我的想法完全不正确?)

年轻的开发人员可能会惊讶地发现,像我这样的年纪越来越大的人过去常常在具有1或2k RAM的系统上用C编写代码

在这种规模的系统中,动态内存分配将是我们无法承受的奢侈。这不仅是管理空闲存储的指针开销,还包括空闲存储碎片的影响,使内存分配效率低下,很可能导致严重的内存不足情况(虚拟内存不是一种选择)

因此,我们使用静态内存分配(即全局变量),对函数嵌套的深度进行非常严格的控制,对嵌套的中断处理进行更严格的控制

在这些系统上写作时,我甚至没有链接标准库。我编写了自己的C启动例程,并提供了自定义的最小I/O例程

我在2k ram系统中编写的一个程序使用ram的下部作为数据区,上部作为堆栈。在最后一个片段中,我证明了堆栈的最大使用在内存中达到了如此之低,以至于它距离数据区域中的最后一个变量只有1字节

啊,过去的好日子

编辑:

为了明确回答您的问题,原始的K&R free store manager用于将头块添加到通过
malloc
分配的每个内存块的开头

标题块如下所示:

union header {
    struct {
    union header   *ptr;
    unsigned        size;
    } s;
};

其中,
ptr
是下一个头块的地址,size是分配的内存大小(以块为单位)。
malloc
函数实际上会返回由
&header+sizeof(header)
计算的地址。free函数将从您提供的指针中减去标题的大小,以便将块重新链接回free列表。

有几种方法可以做到这一点:

  • 编写时,
    malloc()。完全没有效率,所以我把它删掉了
  • malloc()
    100
    int
    s的数组。总共需要
    100*sizeof(int)+1*sizeof(int*)+
    任何
    malloc()
    内部需要的东西。好多了
  • 静态分配数组。这里您只需要
    100*sizeof(int)
  • 在堆栈上分配数组。这需要相同,但仅适用于当前函数调用
您需要哪一个取决于您需要多长时间的内存和其他条件

如果您有那么少的RAM,那么使用
malloc()
是否有用甚至可能会有问题。如果多个代码块需要大量RAM,但不是同时需要,则可以选择此选项

内存地址的跟踪方式也取决于:

  • 对于
    malloc()
    ,必须将指针放在不会丢失的位置
  • 对于堆栈上的数组,它是相对于当前帧指针表示的。代码设置帧,因此知道偏移量,因此通常不需要将其存储在任何位置
  • 对于数据段中的数组,编译器和链接器知道地址,并静态地将地址放在需要的位置
如果这是真的,为什么C语言比汇编语言更受欢迎

你把问题简化得太多了。C或汇编程序——没关系,您仍然需要管理内存块。主要问题是碎片化,而不是实际的管理开销。在您描述的系统中,您可能只分配内存,而从不释放内存,因此无需检查什么是空闲的-水印下的任何内容都是空闲的,仅此而已

真的是这样吗?那么超低效


关于这个问题有很多算法,但是如果你简化的话——是的,基本上是这样。事实上,这是一个更复杂的问题——还有更复杂的系统围绕着内存服务、碎片处理、垃圾收集(在操作系统级别上)等等而运转。

想想看,你真的需要100个带指针的不同整数,还是100个整数的数组,一个指向开头的指针和一个足够大的整数?没错,在这种情况下数组是个好主意-但它仍然必须知道它在哪里?使用一个100
int
s的数组,另一个
int
用于缓冲区的当前大小,另一个用于保持其容量。总共408字节。“分配系统必须以某种方式注意内存在哪里是malloc'd,在哪里是空闲的”,对我来说,这听起来像是瑞士奶酪缓冲区,试着保持缓冲区的紧凑性。
因此超级低效
一个C语言的程序在理想情况下不会比它设计的效率高或低。如果你在堆上不合理地分别分配100个
int
s,那么问题不在于C,而在于你。这不是C的问题,而是操作系统的问题。你可能会更惊讶地发现,这些系统现在仍然在使用。如果你在教统局工作