C语言 realloc() 函数位于 stdlib.h 头文件中,原型为:

void *realloc(void *ptr, size_t size);

realloc() 会将 ptr 所指向的内存块的大小修改为 size,并将新的内存指针返回。
设之前内存块的大小为 n,如果 size < n,那么截取的内容不会发生变化,如果 size > n,那么新分配的内存不会被初始化。

如果 ptr = NULL,那么相当于调用 malloc(size);如果 size = 0,那么相当于调用 free(ptr)。
如果 ptr 不为 NULL,那么他肯定是由之前的内存分配函数返回的,例如 malloc()、calloc()或realloc()。
如果 ptr 所指的内存块被移动,那么会调用 free(ptr)。

一个简单的 realloc() 却赋予了好几个功能,这并不是良好的函数设计。估计也是为了兼容性,才容忍这个函数一直在C库中。虽然在编码中,realloc() 会提供一定的方便,但是也很容易引发Bug。下面是两个常见bug用法:

第1种行为引发的Bug

  1. void *ptr = realloc(ptr, new_size);
  2. if (!ptr) {
  3. // 错误处理
  4. }

这里就引出了一个内存泄露的问题,当realloc() 分配失败的时候,会返回NULL。但是参数中的 ptr 的内存是没有被释放的。如果直接将realloc()的返回值赋给ptr。那么当申请内存失败时,就会造成ptr原来指向的内存丢失,造成内存游离和泄露。

正确的处理应该是这样:

  1. void *new_ptr = realloc(ptr, new_size);
  2. if (!new_ptr) {
  3. // 错误处理。
  4. }
  5. ptr = new_ptr

第2种行为引发的Bug
实际上,malloc(0)是合法的语句,会返还一个合法的指针,且该指针可以通过free去释放。这就造成了很多人对realloc()的错误理解,认为当size为0时,实际上realloc()也会返回一个合法的指针,后面依然需要使用free去释放该内存。

  1. void *new_ptr = realloc(old_ptr, new_size);
  2. //其它代码
  3. free(new_ptr);

由于错误的认识,不去检验new_size是否为0,还是按照new_size不为0的逻辑处理,最后并free(new_ptr)。这里就引入了double free的问题,造成程序崩溃。

所以,realloc() 这个设计并不怎么优良的函数陷阱还是不少的,一不小心就踩雷了,上面只是两个简单的小例子,大家在实际使用的时候还应该注意一些其他小问题。

realloc的使用误区的更多相关文章

  1. 常见CSS与HTML使用误区

       误区一.多div症 <div class="nav"> <ul> <li><a href="/home/"> ...

  2. C# - 值类型、引用类型&走出误区,容易错误的说法

    1. 值类型与引用类型小总结 1)对于引用类型的表达式(如一个变量),它的值是一个引用,而非对象. 2)引用就像URL,是允许你访问真实信息的一小片数据. 3)对于值类型的表达式,它的值是实际的数据. ...

  3. 关于SQL Server镜像的一个小误区

    昨天晚上突然接到客户的电话, 说在配置了镜像的生产环境数据库下修改 “已提交读快照” 选项的时候报错, 需要先取消镜像然后再重新搭建.悲催的是这是个近TB的数据库,问我有没有什么快速的方法.于是我就问 ...

  4. C 语言中 malloc、calloc、realloc 和free 函数的使用方法

    C标准函数库中,常见的堆上内存管理函数有malloc(), calloc(), recalloc(), free(). 之所以使用堆,是因为栈只能用来保存临时变量.局部变量和函数参数.在函数返回时,自 ...

  5. 内存动态分配之realloc(),malloc(),calloc()与new运算符

    1,malloc与free是C/C++的标准库函数,new/delete是C++的运算符,是C++面向对象的特征,它们都可用于申请动态内存和释放内存.2,对于非内部数据类型的对象而言,光用maloc/ ...

  6. SQL Server CheckPoint的几个误区

        有关CheckPoint的概念对大多数SQL Server开发或DBA人员都不陌生.但是包括我自己在内,大家对于CheckPoint都或多或少存在某些误区,最近和高文佳同学(感谢高同学的探讨) ...

  7. Linux C 堆内存管理函数malloc()、calloc()、realloc()、free()详解

    C 编程中,经常需要操作的内存可分为下面几个类别: 堆栈区(stack):由编译器自动分配与释放,存放函数的参数值,局部变量,临时变量等等,它们获取的方式都是由编译器自动执行的 堆区(heap):一般 ...

  8. Fouandation(NSString ,NSArray,NSDictionary,NSSet) 中常见的理解错误区

    Fouandation 中常见的理解错误区 1.NSString //快速创建(实例和类方法) 存放的地址是 常量区 NSString * string1 = [NSString alloc]init ...

  9. css2 [lang|=en] 误区

    [lang|=en] w3c说明:css2选择器,选择以en开头的的lang属性. w3c的这个解释是有误区的,en开头,但是en后面必须要有-,也就是说是选择的是en-开头

随机推荐

  1. C#基础系列——Attribute特性使用

    前言:上篇 C#基础系列——反射笔记 总结了下反射得基础用法,这章我们来看看C#的另一个基础技术——特性. 1.什么是特性:就博主的理解,特性就是在类的类名称.属性.方法等上面加一个标记,使这些类.属 ...

  2. html盒子模型

    http://www.cnblogs.com/sunyunh/archive/2012/09/01/2666841.html

  3. 使用Powershell链接到Office 365

    今天主要讲使用Powershell管理Office 365 可以分为office365用户管理,Exchange Online的管理等 1. 使用Powershell 链接到office 365 用户 ...

  4. ecliplse高亮显示选中的相同变量

    选择:windows-> preferences->java->Editor->Mark Occurences 选择最上的复选框,下面的就有很多了. 其中的Local vari ...

  5. C#文本写入文件,追加写入文件

    写入文件和这个对象 StreamWriter using (StreamWriter fs = new StreamWriter(path, true)) { fs.WriteLine(strLog) ...

  6. R语言排序:sort(),rank(),order()示例

    > x<-c(97,93,85,74,32,100,99,67) > sort(x) [1] 32 67 74 85 93 97 99 100 > order(x) [1] 5 ...

  7. wait、notify、sleep、interrupt对比分析

    对比分析Java中的各个线程相关的wait().notify().sleep().interrupt()方法 方法简述 Thread类 sleep:暂停当前正在执行的线程:(类方法) yield:暂停 ...

  8. ubuntu下安装mysql及卸载mysql方法

    1. 删除mysql a. sudo apt-get autoremove --purge mysql-server-5.0 b. sudo apt-get remove mysql-server c ...

  9. 大熊君大话NodeJS之 ------ Connect中间件第二季(源码分析)

    一,开篇分析 大家好,大熊君又回来了,今天这篇文章主要是对"Connect"中间件以及相关辅助中间件,做一个源码分析系列,我想上一篇文章大家也看了, 介绍了使用方式及用途,而这篇也 ...

  10. Android之仿微信Tab滑动

    这个项目实现了以下的功能:有三个标签聊天.发现和通讯录,左右滑动下面的ViewPager可以切换不同的标签,且标签下面的蓝色条可以随着手指的滑动来实时滑动.另外,如果第二次滑动到“聊天”界面,可以在“ ...