malloc realloc calloc free
自上次发现自己对这几个C函数不熟悉,就打算抽空整理一下,也就现在吧。这几个函数都是跟堆内存打交道的,还有一个好玩的函数--alloca,它是跟栈内存打交道的,我想留在以后研究出好玩点的来,再专门为其写一篇铭文。
1.malloc:
头文件:<stdlib.h>
原型:extern void *malloc(unsigned int num_bytes);
功能:分配长度为num_bytes字节的内存块。如果分配成功则返回指向被分配内存的指针,否则返回NULL。
机理:malloc函数的实质体现在,它有一个将可用的内存块连接为一个长长的列表的所谓空闲链表。调用malloc函数时,它沿连接表寻找一个大到足以满足用户请求所需要的内存块。然后,将该内存块一分为二(一块的大小与用户请求的大小相等,另一块的大小就是剩下的字节)。接下来,将分配给用户的那块内存传给用户,并将剩下的那块(如果有的话)返回到连接表上。调用free函数时,它将用户释放的内存块连接到空闲链上。到最后,空闲链会被切成很多的小内存片段,如果这时用户申请一个大的内存片段,那么空闲链上可能没有可以满足用户要求的片段了。于是,malloc函数请求延时,并开始在空闲链上翻箱倒柜地检查各内存片段,对它们进行整理,将相邻的小空闲块合并成较大的内存块。如果无法获得符合要求的内存块,malloc函数会返回NULL指针,因此在调用malloc动态申请内存块时,一定要进行返回值的判断。
2.realloc:
头文件:<stdlib.h>
原型:extern void *realloc(void *mem_address, unsigned int newsize);
功能:改变指针mem_address所指向区域的大小为newsize。如果成功则返回指针mem_address,否则返回NULL。
机理:先判断当前的指针mem_address是否有足够的连续空间,如果有,扩大mem_address指向的地址,并且将mem_address返回,如果空间不够,先按照newsize指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来mem_address所指内存区域(注意:原来指针是自动释放,不需要使用free),同时返回新分配的内存区域的首地址。即重新分配存储器块的地址。
3.calloc:
头文件:<stdlib.h>
原型:void* calloc(size_t n, size_t size);
功能: 在内存的动态存储区中分配n个长度为size的连续空间,函数返回一个指向分配起始地址的指针;如果分配不成功,返回NULL。
机理:在malloc的基础上加上内存空间清0操作。
4.free:
头文件:<stdlib.h>
原型:void free (void* ptr);
功能:释放指针ptr指向的堆内存。
5.Example
#include <stdlib.h> /* malloc, calloc, realloc, free */ int main ()
{
int * buffer1, * buffer2, * buffer3;
buffer1 = (int*) malloc (*sizeof(int));
buffer2 = (int*) calloc (,sizeof(int));
buffer3 = (int*) realloc (buffer2,*sizeof(int));
free (buffer1);
free (buffer3);
return ;
}
下面是好玩的地方:
1.malloc与calloc的区别:函数malloc不能初始化所分配的内存空间,而函数calloc能。函数calloc() 会将所分配的内存空间中的每一位都初始化为零,也就是说,如果你是为字符类型或整数类型的元素分配内存,那么这些元素将保证会被初始化为0;如果你是为指针类型的元素分配内存,那么这些元素通常会被初始化为空指针;如果你为实型数据分配内存,则这些元素会被初始化为浮点型的零.
2.realloc需要注意的安全问题:
(1)从realloc的机理得知,其返回的地址不一定是原地址,这点尤为重要. realloc可以对给定的指针所指的空间进行扩大或者缩小,无论是扩张或是缩小,原有内存的中内容将保持不变.当然,对于缩小,则被缩小的那一部分的内容会丢失.realloc并不保证调整后的内存空间和原来的内存空间保持同一内存地址.相反,realloc返回的指针很可能指向一个新的地址.
(2)下面说下realloc的扩展:
void *ptr = realloc(ptr, new_size);
if (!ptr) {
错误处理
}
这里就引出了一个内存泄露的问题,当realloc分配失败的时候,会返回NULL。但是参数中的ptr的内存是没有被释放的。如果直接将realloc的返回值赋给ptr。那么当申请内存失败时,就会造成ptr原来指向的内存丢失,造成泄露。
正确的处理应该是这样:
void *new_ptr = realloc(ptr, new_size);
if (!new_ptr) {
错误处理。
}
ptr = new_ptr
<2>
void *new_ptr = realloc(old_ptr, new_size);
//其它代码
...... ......
这种bug由一种不好的编程习惯引发的。即认为申请内存始终可以成功,因此并不检查malloc的返回值。这在一般情况下,不会引发问题。但是对于realloc来说,当new_size为0时,realloc返回NULL。而在后面的代码上,继续使用new_ptr,比如会导致程序crash。
malloc realloc calloc free的更多相关文章
- c的三个内存分配函数(malloc,realloc,calloc)
//内存分配_malloc int main(){ int *p; char *p1; p=(int *)malloc(sizeof(*p)*size);//size为需要存储的数量 p1=();// ...
- Linux C 堆内存管理函数malloc()、calloc()、realloc()、free()详解
C 编程中,经常需要操作的内存可分为下面几个类别: 堆栈区(stack):由编译器自动分配与释放,存放函数的参数值,局部变量,临时变量等等,它们获取的方式都是由编译器自动执行的 堆区(heap):一般 ...
- malloc,calloc,realloc,alloc
三个函数的申明分别是: void* realloc(void* ptr, unsigned newsize); void* malloc(unsigned size); void* calloc(si ...
- malloc,calloc,realloc函数用法,原理及不同解析
https://blog.csdn.net/lixungogogo/article/details/50887028 一.malloc malloc在MSDN中原型为: void *malloc( s ...
- 【C/C++开发】malloc,calloc和realloc的区别和注意事项
(1)C语言跟内存分配方式 <1>从静态存储区域分配. 内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.例如全局变量.static变量. <2&g ...
- malloc,calloc,realloc
与堆操作相关的两个函数 malloc #include<stdio.h> #include<stdlib.h> #include<string.h> int mai ...
- malloc()与calloc差别
Both the malloc() and the calloc() functions are used to allocate dynamic memory. Each operates slig ...
- malloc、calloc、relloc
1.malloc void * malloc(size_t _Size); malloc函数在堆中分配参数_Size指定大小的内存,单位:字节,函数返回void *指针. 2.calloc void ...
- malloc()与calloc区别 (转)
另外说明: 1.分配内存空间函数malloc 调用形式: (类型说明符*) malloc (size) 功能:在内存的动态存储区中分配一块长度为"size" 字节的连续区域.函数的 ...
随机推荐
- 安装WampServer关闭mysql服务后打不开了(端口冲突)
1.WampServer自带了mysql精简班的数据库了 2.WampServer自带 的mysql和你独立安装的mysql端口号冲突了 3.mysql默认的端口号是3306 4.建议你修改WampS ...
- anycast简单总结
一针见血,言简意赅的总结 bgp+anycast就是不同服务器用了相同的ip地址 anycast 技术特点 bgp+anycast就是多个主机使用相同ip地址的一种技术,当报文发给该地址时,根据路由协 ...
- sql的一些事件处理
select getdate() select Convert(varchar(10),getdate(),120) yyyy-mm-ddselect Convert(varchar(20),getd ...
- Spring入门一----HelloWorld
知识点: 简介 HelloWorld 简介: 百度百科 HelloWorld 项目结构图: 导入Spring支持包: 然后选中所有包,右键Build Path à Add to Buil ...
- RTMP(实时信息传输协议)详解
RTMP协议是Real Time Message Protocol(实时信息传输协议)的缩写,它是由Adobe公司提出的一种应用层的协议,用来解决多媒体数据传输流的多路复用(Multiplexing) ...
- python 生成器和生成器表达式
1.生成器 生成器的本质就是迭代器 生成器的特点和迭代器一样.取值方式和迭代器一样(__next__(),send():给上一个yield传值) 生成器一般由生成器函数或者生成器表达式来创建 其实就是 ...
- Java堆外内存之七:JVM NativeMemoryTracking 分析堆外内存泄露
Native Memory Tracking (NMT) 是Hotspot VM用来分析VM内部内存使用情况的一个功能.我们可以利用jcmd(jdk自带)这个工具来访问NMT的数据. NMT介绍 工欲 ...
- 第八章 搭建hadoop2.2.0集群,Zookeeper集群和hbase-0.98.0-hadoop2-bin.tar.gz集群
安装配置jdk,SSH 一.首先,先搭建三台小集群,虚拟机的话,创建三个 下面为这三台机器分别分配IP地址及相应的角色:集群有个特点,三台机子用户名最好一致,要不你就创建一个组,把这些用户放到组里面去 ...
- vptr, vtable, virtual base class table
#include <iostream> using namespace std; class X { int x, y, z; }; class Y: public virtual X { ...
- 工具类MyBatisUtils创建SqlSessionFactory
package com.js.ai.modules.pointwall.interfac; import java.io.IOException; import java.io.InputStream ...