天天看点

详解C语言中内存分配函数

详解C语言中内存分配函数

很多新学C语言的童鞋在用到动态内存分配的时候,对选择哪种分配函数及其有何区别搞不清楚,那么下文就认真的讲讲它们的种种。

(1)C语言的内存分配方式

  • 从静态存储区域分配

    这些在程序编译的时候就已经分配好,且在程序的整个运行期间都固定不变。

使用这种方式分配内存空间的数据主要包括:

代码段(DATA Section)的程序自身语句文本(包括嵌在代码里的字符串常量),已经初始化的全局变量和静态变量 。

.BSS段的未初始化的全局变量。

  • 在栈stack上分配

这种方式由系统自动分配,函数退出时也由系统自动释放。

使用这种方式分配内存空间的数据主要包括:

本地变量和函数参数

  • 从堆heap上分配,亦称动态内存分配

程序在运行的时候用malloc类或new动态申请的内存,由用户自己负责用free或delete释放。动态内存的生存期由用户决定,使用非常灵活,但问题也最多。

使用这种方式分配内存空间的数据主要包括:

自定义输入缓存或用于接收用户输入数据的变量(数组、结构体等)

(2)跟内存申请相关的函数

void* malloc(size_t size)

作用:从堆中分配size个字节的空间,成功则返回空间首地址,失败则返回空指针。它的声明位于stdlib.h头文件中。

我们在编程中必须注意分配失败的情况,以使程序更加健壮和完备。所以一般会对其进行包装:

void *
xmalloc (size_t size)
{
    void *value = malloc (size);
    if (value == 0)
        fatal ("virtual memory exhausted");
    return value;
}      

同时,由于它并没有对分配的空间进行任何操作,因此基本上malloc之后,需要调用函数memset来初始化。

struct foo *ptr;
...
ptr = (struct foo *) malloc (sizeof (struct foo));
if (ptr == 0) 
    abort ();
memset (ptr, 0, sizeof (struct foo));      

void * calloc (size_t count, size_t eltsize)

作用:从堆中分配size个字节的已经清零的空间,成功则返回空间首地址,失败则返回空指针。它的声明位于stdlib.h头文件中。

它的实现等同于:

void *
calloc (size_t count, size_t eltsize)
{
    size_t size = count * eltsize;
    void *value = malloc (size);
    if (value != 0)
        memset (value, 0, size);
    return value;
}      

void * realloc (void *ptr, size_t newsize)

作用:用来对之前申请的动态内存重新进行分配大小(扩容或缩小)。

参数解释:ptr必须为之前通过malloc或calloc等函数申请的动态内存首地址;newsize为你现在需要的大小。

注意事项:

1 如果是扩容,它不能保证后加的空间一定是接在原来申请的内存空间之后的,因为有可能其之后的空间已经被使用了。此时系统会找一块大小符合你要求的连续空间,并同时把原来空间内容复制到新空间,最后再释放原空间。

2 如果扩容失败,则原空间内容不受影响。

3 如果参数ptr为空,则其动作同malloc。

但是当我们使用时,为了程序的健壮性和完备性,在使用时我们需要包装一下:

void *
xrealloc (void *ptr, size_t size)
{
    void *value = realloc (ptr, size);
    if (value == 0)
        fatal ("Virtual memory exhausted");
    else
        return value;      

void * reallocarray (void *ptr, size_t nmemb, size_t size)

void * aligned_alloc (size_t alignment, size_t size)