原理:malloc函数的实质体现在,它有一个将可用的内存块连接为一个长长的列表的所谓空闲链表。调用malloc函数时,它沿连接表寻找一个大到足以满足用户请求所需要的内存块。然后,将该内存块一分为二(一块的大小与用户请求的大小相等,另一块的大小就是剩下的字节)。接下来,将分配给用户的那块内存传给用户,并将剩下的那块(如果有的话)返回到连接表上。调用free函数时,它将用户释放的内存块连接到空闲链上。到最后,空闲链会被切成很多的小内存片段,如果这时用户申请一个大的内存片段,那么空闲链上可能没有可以满足用户要求的片段了。于是,malloc函数请求延时,并开始在空闲链上翻箱倒柜地检查各内存片段,对它们进行整理,将相邻的小空闲块合并成较大的内存块。如果无法获得符合要求的内存块,malloc函数会返回NULL指针,因此在调用malloc动态申请内存块时,一定要进行返回值的判断。
Linux Libc6采用的机制是在free的时候试图整合相邻的碎片,使其合并成为一个较大的free空间。
头文件: #include <stdio.h> 函数原型: void *malloc(size_t size); 参数说明: size:待分配内存字节数量的参数,size_t为一个无符号整型。 返回值: void*: malloc函数可以保证其返回的内存地址是对齐的,所以void *可以类型转换为任何类型的数据。返回NULL表示无法分配。
他为一个结构数据分配内存,并且需要元素个数以及元素的尺寸作为其参数。分配的内存会使用0进行填充。
头文件: #include <stdio.h> 函数原型: void *calloc(size_t number_of_elements, size_t element_size); 返回值: void*: 返回一个指向第一个元素的指针。返回NULL表示无法分配。与malloc函数类似,其后的调用并不会返回连续的空间, 所以我们不可能通过简单的再次调用calloc函数并且期望第二次调用所返回的内存添加到第一次调用的结束处,从而来扩大由calloc所分配的内存空间。
#include <stdio.h> #include <stdlib.h> #include <string.h> int main(void) { char *str = NULL; /* 分配内存空间 */ str = (char*) calloc (10, sizeof(char)); /* 将hello写入*/ strcpy(str, "Hello"); /*显示变量内容*/ printf("String is %s\n", str); /* 释放空间 */ free(str); return 0; }
realloc会改变前一次分配的内存块的尺寸。
头文件: #include <stdio.h> 函数原型: void *realloc(void *existing_memory, size_t new_size); 返回值: void*: 返回一个指向第一个元素的指针。返回NULL表示无法分配。注意点1:realloc也许会需要能过移动数据来达到此目的,所以很重要的一点就是要保证一旦内存被重新分配了,我们必须使用新的指针,而不要试图使用realloc调用以前的指针来访问内存。
头文件: #include <stdlib.h> 函数原型: void free(void *ptr) 参数说明: ptr:调用free时使用的参数指针必须是指向由malloc、calloc或realloc调用所分配的内存使用示例:
#include <stdio.h> #define ONE_K (1024) int main() { char *some_memory; int exit_code = EXIT_FAILURE; some_memory = (char *)malloc(ONE_K); if (some_memory != NULL) { free(some_memory); exit_code = EXIT_SUCCESS; } exit(exit_code); }
Q:C语言中,free()函数怎么知道释放多大的空间?
在C语言中,可以传递任意类型的指针作为free()函数的参数,但是free()函数怎么知道需要释放多少已分配的内存空间呢?当传递一个指针给某些函数的同时,不得不传递相应的所占空间的大小(例如,10个char类型的元素组成的数组,作为函数参数的同时,需要将其长度10作为函数参数传递),但是,并没有传递给free()指针所指向空间的大小啊。
A:通常,当malloe()等内存分配函数分配一块内存时,它们所获取的内存总是比所要求的稍大一些。它们返回的并不是这块内存的起始地址,而是一个比起始地址稍往后一点的一个地址。一些有关信息,例如所分配的内存块的大小,将被存放在这两个地址之间的那部分区域中
(如果这部分内容被改写,当所分配的这块内存被释放后你的程序中就会出现野指针)。这样,只要检查这部分信息,free()()函数就能知道要释放的内存块的大小了。
许多应用程序只需要能够针对某个资源创建一个锁文件(其实就是一个普通文件),然后其他程序通过检查这个文件(是否存在的状态)来判断它们是否被允许访问某个资源。简而言之,就是使用“系统不允许创建同名文件”这个限制来假借普通文件实现锁机制。创建锁文件使用fcntl.h头文件定义的open系统调用,并带上O_CREAT和O_EXCL标志。这样就以原子操作完成两项工作:确定文件不存在,然后创建之。
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <fcntl.h> #include <errno.h> const char *lock_file = "/tmp/LCK.test"; int main() { int file_desc; int tries = 10; while (tries--) { file_desc = open(lock_file, O_RDWR | O_CREAT | O_EXCL, 0444); if (file_desc == -1) //creating file failed { printf("%d - Lock already present\n", getpid()); sleep(2); } else //进入临界区 { printf("%d - I have exclusive access\n", getpid()); sleep(1); (void)close(file_desc); (void)unlink(lock_file);//leave critical section sleep(2); } } exit(EXIT_SUCCESS); }