简体   繁体   English

C中的malloc内存分配方案

[英]malloc memory allocation scheme in C

I was experimenting with malloc in C and I have observed that malloc is wasting some space after some memory has been allocated. 我在C中试验了malloc,我观察到malloc在分配了一些内存后浪费了一些空间。 Below is the piece of code I used to test malloc 下面是我用来测试malloc的代码片段

#include <stdlib.h>
#include <string.h>

int main(){
    char* a;
    char* b;
    a=malloc(2*sizeof(char));
    b=malloc(2*sizeof(char));
    memset(a,9,2);
    memset(b,9,2);
    return 0;
}

In the right-middle of the following picture(open the image in a new tab for clarity) you can see the memory contents;0x804b008 is the address pointed by variable 'a' and 0x804b018 is the memory pointed by variable 'b'. 在下图的右下方(为清晰起见,在新选项卡中打开图像),您可以看到内存内容; 0x804b008是变量'a'指向的地址,0x804b018是变量'b'指向的内存。 what is happening to memory between from 0x804b00a 0x804b017? 从0x804b00a 0x804b017到内存发生了什么? The thing is even if I try to allocate 3*sizeof(char) instead of 2*sizeof(char) bytes of memory the memory layout is the same! 即使我尝试分配3*sizeof(char)而不是2*sizeof(char)字节的内存,内存布局是相同的! So, is there something I am missing? 那么,有什么我想念的吗?

gdb接口

malloc() is allowed to waste as much space as it wants to - the standard doesn't specify anything about the implementation. 允许malloc()浪费尽可能多的空间 - 标准没有指定任何有关实现的内容。 The only guarantee you have is about alignment ( §7.20.3 Memory management functions ): 唯一的保证是关于对齐( §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). 如果分配成功,则返回的指针被适当地对齐,以便可以将其指定给指向任何类型对象的指针,然后用于在分配的空间中访问此类对象或此类对象的数组(直到空间被显式释放) 。

Your implementation appears to return you minimum-8-byte-aligned pointers. 您的实现似乎返回最小8字节对齐的指针。

Memory Alignment! 记忆对齐! It's good for perfomance in x86 and mandatory in some architectures like ARM. 这对于x86中的性能是有利的,并且在ARM等某些体系结构中是强制性的。

Most CPUs require that objects and variables reside at particular offsets in the system's memory. 大多数CPU要求对象和变量驻留在系统内存中的特定偏移处。 For example, 32-bit processors require a 4-byte integer to reside at a memory address that is evenly divisible by 4. This requirement is called "memory alignment". 例如,32位处理器需要一个4字节的整数驻留在一个可被4整除的存储器地址。这个要求称为“存储器对齐”。 Thus, a 4-byte int can be located at memory address 0x2000 or 0x2004, but not at 0x2001. 因此,一个4字节的int可以位于存储器地址0x2000或0x2004,但不能位于0x2001。 On most Unix systems, an attempt to use misaligned data results in a bus error, which terminates the program altogether. 在大多数Unix系统上,尝试使用未对齐的数据会导致总线错误,从而完全终止程序。 On Intel processors, the use of misaligned data is supported but at a substantial performance penalty. 在英特尔处理器上,支持使用未对齐的数据,但性能会受到严重影响。 Therefore, most compilers automatically align data variables according to their type and the particular processor being used. 因此,大多数编译器会根据数据类型和所使用的特定处理器自动对齐数据变量。 This is why the size that structs and classes occupy is often larger than the sum of their members' 这就是为什么结构和类占用的大小通常大于其成员的总和的原因

http://www.devx.com/tips/Tip/13265 http://www.devx.com/tips/Tip/13265

The heap is handled by the implementation, not necessarily as you expect. 堆由实现处理,不一定如您所期望的那样。 The Standard explicitly doesn't guarantee anything about order or contiguity. 标准明确不保证任何有关订单或连续性的内容。 There are two main things that cause more heap space to be used than you asked for. 有两个主要因素导致使用的堆空间比您要求的多。

First, allocated memory has to be aligned so that it's suitable for use by any sort of object. 首先,必须对齐已分配的内存,以便它适合任何类型的对象使用。 Typically, computers expect primitive data objects of N bytes to be allocated at a multiple of N, so the odds are you can't get malloc() to return a value that isn't a multiple of 8. 通常,计算机期望N个字节的原始数据对象以N的倍数分配,因此您无法获得malloc()以返回不是8的倍数的值。

Second, the heap needs to be managed, so that free() allows reuse of the memory. 其次,需要管理堆,以便free()允许重用内存。 This means that the heap manager needs to keep track of allocated and unallocated blocks, and their sizes. 这意味着堆管理器需要跟踪已分配和未分配的块及其大小。 One practice is to stick some information in memory just before each block, so the manager can know what size block to free and where blocks are that might be reused. 一种做法是在每个块之前将一些信息粘贴到内存中,这样管理器就可以知道要释放的块大小以及可以重用的块。 If that's what your system does, there will be more memory used between allocated blocks, and given alignment restrictions at 8 bytes it's likely you can't get allocations of less than 16 bytes. 如果这是你的系统所做的,那么在分配的块之间会有更多的内存,并且在8字节给定对齐限制时,你可能无法获得少于16字节的分配。

Most modern malloc() implementations allocate in powers of two and have a minimum allocation size, to reduce fragmentation since oddball sizes could generally only be reused when enough contiguous allocations are free() d to make larger blocks. 大多数现代malloc()实现以2的幂分配并具有最小分配大小,以减少碎片,因为奇数球大小通常只有在足够的连续分配free()时才能重复使用free() d来制作更大的块。 (It also speeds up coalescing contiguous allocations in general, IIRC.) Also keep in mind the block overhead; (它还加速了整合的连续分配,IIRC。)还要记住块开销; to get the block size you need to add some amount (8 in GNU malloc() , IIRC) for internal management uses. 要获得块大小,您需要添加一些金额(GNU malloc() ,IIRC中的8个)以供内部管理使用。

malloc is only guaranteed to return you a block of memory that's at least as big as the size you give it. malloc只保证返回一块至少和你给它一样大的内存块。 However, processors are generally more efficient when they're operating on blocks of memory that start at multiples of, say, 8 bytes in memory. 但是,当处理器在内存块上运行时,处理器通常会更高效,这些内存块以内存中的8个字节的倍数开始。 Look up word size for more information on this. 查找字大小以获取更多信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM