Unix C的内存分配与释放

tech2022-08-22  123

文章目录

简介标准C的动态内存分配与释放Unix C的动态内存分配与释放模型图例代码示例 malloc和sbrk的区别内存分配调用链路

简介

Unix中应用程序操作的都是虚拟内存,而虚拟内存与物理内存存在一个映射,映射最小单位为页,一页为4096个字节。 内存分配就是指建立一块虚拟内存与物理内存之间的映射。释放内存就是解除虚拟内存与物理内存的映射。

标准C的动态内存分配与释放

C中有多个存储类别,分别为:静态存储期、线程存储期、自动存储期、动态分配存储期。 所有内存都需要预留足够的空间来存放数据,在函数中定义的非static变量都为属于自动存储期,在函数的入栈时,程序会自动分配局部变量的内存,在函数出栈会自动释放内存。而动态内存,由标C的malloc()函数来分配,由malloc分配的内存必须由free()函数来释放。函数在头文件为<stdlib.h>中定义。

函数描述void *malloc(size_t size);该函数分配size个字节的内存,并返回一个指向它的指针。void free(void *ptr);释放ptr指向的内存空间,ptr必须是malloc()、calloc()、realloc()函数返回的指针。如果在free之前,已经被free过,这种行为是没有定义的,会出问题。如果ptr是NULL,则不会执行任何动作。 #include <stdio.h> #include <stdlib.h> int main(void) { int *pi = malloc(sizeof(int)); //分配一个int类型所需的字节大小内存 if (!pi) { //分配内存出错返回NULL perror("malloc"); //当分配内存出错打印错误信息 return -1; } *pi = 10; printf("%d\n", *pi); free(pi); int *pi2 = malloc(0xffffffffffffffff);//分配一个无法分配的内存大小 if (!pi2) { //分配内存出错返回NULL perror("malloc"); //当分配内存出错打印错误信息 return -1; } *pi2 = 10; printf("%d\n", *pi2); free(pi2); return 0; } 10 malloc: Cannot allocate memory

Unix C的动态内存分配与释放

在Unix中通过sbrk()函数来更改数据快的大小来实现内存分配,该函数通过操作堆顶指针的移动来进行内存的分配与释放。在Unix中,malloc()和free()实际也是通过调用sbrk()来实现的内存分配。

函数描述void *sbrk(intptr_t increment);增加increment个字节大小的程序数据空间。传入0,则返回当前已分配的内存空间的结束位置的指针(当前堆顶指针)。int brk(void *addr);直接将堆顶移动到addr位置。多用于传入指向分配内存之前的指针来达到一次性清空释放内存的目的。

模型图例

代码示例

#include <stdio.h> #include <unistd.h> #include <string.h> int main(void) { setbuf(stdout, NULL); //关闭print缓冲区 void *initp = sbrk(0); //当前堆指针位置 printf(" 初始堆顶:%p\n", initp); int *pi = sbrk(sizeof(int)); //分配一个int类型字节的内存 printf(" 分配1个int字节内存:%p\n", pi); *pi = 10; printf("%d\n", *pi); char *pc = sbrk(sizeof(char) * 8); //分配8个char类型字节大小的数组 printf("分配8个char字节内存:%p\n", pc); strcpy(pc, "abc"); printf("%s\n", pc); char *fp = sbrk(-8); printf("释放8个char字节内存:%p\n", fp); printf(" 当前堆顶指向位置:%p\n", sbrk(0)); printf("一次性释放内存\n"); brk(initp); printf(" 当前堆顶指向位置:%p\n", sbrk(0)); return 0; } 初始堆顶:0x20de000 分配1个int字节内存:0x20de000 10 分配8个char字节内存:0x20de004 abc 释放8个char字节内存:0x20de00c 当前堆顶指向位置:0x20de004 一次性释放内存 当前堆顶指向位置:0x20de000

通过结果可以看出地址的增长和减少。

malloc和sbrk的区别

malloc()分配的内存,可以直接free,也就是说可以将一个内存区中间的某部分free掉。但是只是逻辑上释放了,标记了该块内存可以被下次重新分配,实际物理内存并没释放,只是由程序内部通过链表不连续的内存块串起来了。 sbrk()是一个典型的栈模型,通过移动边界指针来控制内存的分配与释放,并且只能在堆顶分配和释放。

内存分配调用链路

最新回复(0)