使用C/C++的苦逼娃们经常深陷内存越界错误,资源泄漏错误等等问题,而且这样的惨剧每时每刻都在这个世界上重复的发生着。其实,我也是苦逼娃!也为了个神马越界的东西debug了整个下午过,为此也想砸电脑过。最后想想,其实不是C/C++苦逼,是我们的不小心而造成如此的苦逼。罪过,罪过。。。

在C语言库中,提供了这么两个函数,malloc和free,分别用于执行动态内存分配和释放。两个函数的声明如下:

void* malloc(size_t size);
void free(void *pointer);

从外观上看,malloc函数的参数是接受需要分配的内存字节数,如果内存能够满足请求量,那么将会返回:指向被分配的内存块起始位置的指针(引用自《C和指针》中的表述)。而且,这块内存是一块连续的内存。够爽吧!如果分配不成功的话,那么就返回null指针。例如:

struct Node
{
    data_type value;
    struct Node *pre_node;
    struct Node *next_node;
};
 
typedef struct Node *List;
 
List newnode = NULL;
 
newnode = (List)malloc(sizeof(struct Node));  // 分配了Node的空间,返回了相应的指针
 
if (!newnode)                                // 为了防止空指针的存在,要检查是否分配成功
{
    printf("内存分配不成功!\n");
    exit(1);
}

在这里,我们又一次看到了void指针的功效。对于不同类型的指针转换,void指针都能应付自如,更重要的是,我们不用为每种类型都特化一个内存分配版本。这个会累死的。还有,对于分配出来的指针,我们要检查它是否为空,这是为什吗?因为,对于空指针的操作将会带来未知的错误,所以错误摁在萌芽阶段是我们的义务和责任。

内存的东西,向来都是要有借有还。有malloc就会有free。free函数的作用就是负责释放申请来的内存的。这个指向释放的内存指针是有讲究的,你不能释放申请来的一小部分的区域。例如:

int *pi;
 
pi = (int *)malloc(sizeof(int)*10);
 
free(pi + 5);    // 这里就苦逼了!

其次,较为常见失误在于,我们对申请的内存指针进行操作,操作完之后,对其进行释放。此时,释放不成功的原理和上面这个例子一样,释放了部分的内存,而不是释放全部内存。一般的做法是设一个临时变量保存malloc来的指针,在释放的时候,就释放这个指针所以的内存区域,这样就不会出错了。

关于内存越界,这是一个很普遍的问题。这个只能你去亲自把握,记清楚你申请了多少,其边界在哪里,不要出错就埋怨电脑。

说了malloc和free,那就进入今天的主题new和delete了。

想必我们都写过这样的代码吧

string *str = new string("memory alloc!");

我们都知道new在堆上创建了一个string类型对象,这个看似一个动作的事情却暗地包含了三件事:获得一块内存空间、调用构造函数、返回正确的指针。相当于下面:

void *pstr = operator new(sizeof(string));
new(pstr) string("memory alloc!");
string *str = static_cast<string*>(pstr);

你应该会心里犯嘀咕,卧槽,怎么出现了这么多的环节。其实呢,new可分为这么三种情形:new operator(我们平常用的new), operator new(用来分配内存的),placement new(构造对象的)。当然,你要用placement new的时候,你要加入<new>的头函数。

⑴ new operator

new operator的第一步分配内存实际上是通过调用operator new来完成的,这里的new是可以重载的。operator new默认情况下首先调用分配内存的代码,尝试得到一段堆上的空间,如果成功就返回,如果失败,则转而去调用一个new_hander,然后继续重复前面过程。

#include <iostream>
using namespace std;
 
class MyClass {
private:
 
public:
    MyClass() { };
 
    void* operator new(size_t size)
    {
        cout << "调用了operator new" << endl;
        return ::operator new(size);
    }
};
 
int main()
{
    MyClass *a = new MyClass();
    return 0;
}

运行的结果如下:

相应的,delete也有delete operator和operator delete之分,后者也是可以重载的。并且,如果重载了operator new,就应该也相应的重载operator delete。

⑵ placement new

placement new的作用是用来实现定位构造对象,可以说相当于new operator三步操作中的第二步,也就是在取得了一块可以容纳指定类型对象的内存后,在这块内存上构造一个对象。其用法

void construct(pointer __p, const _Tp& __val) { new(__p) _Tp(__val); }

其格式是这样的:new(指针指向的内存地址) 类型(值)。对照格式,可以这么说是在__p上构造一个_Tp类型的,值为__val。

如果是像上面那样在栈上使用了placement new,则必须手工调用析构函数:

void destroy(pointer __p) { __p->~_Tp(); }

当觉得默认的new operator对内存的管理不能满足我们的需求,我们可以自己手工打造内存管理,此时的placement new就相当有用了。以上两段代码源于sgi stl的alloc中,就说明问题了

⑶ new operator 和 operator new 的取舍

两个关键词很容易让人迷糊,两者又都是骨肉相连的状态,取舍有点不易。对于取舍的评判,我挪用了《more effective C++》中的观点:“如果你想产生对象在heap上,那么就用new operator,它不但分配内存,而且为该对象调用了构造函数;如果你只打算分配内存,那么就用operator new ,只分配内存,其余的事情都没做。当然,使用operator new 后续的对象构造也要跟上,不然但分配内存也就没有意义了。”

总结,在这篇文章中,介绍了malloc,free,new,delete的使用和一些心得体会。当然,还有许多的内容没有做相应的介绍,比如new_handle等内容。抱歉,抱歉!

关于内存分配的问题,你还可以参考:内存分配机制。这篇文章介绍了C/C++内存分配的知识。

参考文献

1. 《C语言程序设计》

2. 《C和指针》

3. 《C专家编程》

4. 《more effective C++》

5. 《STL源码解析》

转载于:https://www.cnblogs.com/ComputerG/archive/2012/03/10/2389328.html

malloc,free,new,delete解析(原)相关推荐

  1. malloc/new函数及malloc()的一种简单原理性实现

    malloc函数 void *malloc(int size); 说明:malloc 向系统申请分配指定size个字节的内存空间.返回类型是 void* 类型.void* 表示未确定类型的指针.C,C ...

  2. C++/C语言申请动态空间的详解【new关键字、malloc关键字、delete和free关键字】

    文章目录 [1] C++ ->new关键字 [2] C语言->malloc关键字 [3]C++/C->delete和free关键字 [1] C++ ->new关键字 new: ...

  3. 小白解析原画正确的学习方向以及方法,萌新如何迈出画画第一步

    学习原画初学时如何提升原画绘画的能力?可以这样说,绘画是内心想法的表达工具,设计理念再好,也需要正确的表达.对于初学者来说绘画的能力又更为重要. 1.多画多练,从最基础的草稿.体块.结构等入手练习.造 ...

  4. 原生与html,解析原生与html之间进行的一些关联

    1.Android中设置部分字体的颜色改变,并且能点击 1, 使用SpannableStringBuilder来实现//1,使用 SpannableStringBuilder , 参数中的数字表示修改 ...

  5. malloc,new,fre,delete最全面试题总结

  6. ZZ:new/delete 和malloc/free 的区别

    相同点:都可用于申请动态内存和释放内存 不同点: (1)操作对象有所不同. malloc与free是C++/C 语言的标准库函数,new/delete 是C++的运算符.对于非内部数据类的对象而言,光 ...

  7. new/delete与malloc/free的区别和联系

    1.new 是c++中的操作符,malloc是c 中的一个函数 2.new 不止是分配内存,而且会调用类的构造函数,同理delete会调用类的析构函数,而malloc则只分配内存,不会进行初始化类成员 ...

  8. C++ new/delete、malloc/free

    2019独角兽企业重金招聘Python工程师标准>>> http://www.cnblogs.com/growup/archive/2011/06/27/2091101.html h ...

  9. 百度笔试题:malloc/free与new/delete的区别

    相同点:都可用于申请动态内存和释放内存 不同点: (1)操作对象有所不同. malloc与free是C++/C 语言的标准库函数,new/delete 是C++的运算符.对于非内部数据类的对象而言,光 ...

最新文章

  1. MATLAB 表数据结构最终篇,如何实现表操作
  2. 在Python中的无参装饰器和有参装饰器
  3. 20110609 搭域控,布线,设计网络,杂事一堆啊
  4. docker copy异常
  5. 垃圾代码评析——关于《C程序设计伴侣》9.4——链表(一)
  6. 数学之路(3)-机器学习(3)-机器学习算法-欧氏距离(3)
  7. 利用VS2005进行dump文件调试
  8. 企业请专职SEO和外包给科技公司做优化,有什么不同?
  9. DDCTF2018-黑盒破解 详细WP
  10. C语言将标准时间转成秒,c标准时间与时间戳转换
  11. 基于STM32MP1的IOT参考设计(采用QT和web技术)
  12. Canvas 绘制圆形图片、绘制圆角矩形图片
  13. 【Linux(一)】最新VMware虚拟机下载与安装
  14. 爱国html源码,鼠标点击网页爱国富强民主特效(附代码)
  15. GridView相关
  16. 一位中科院自动化研究所博士的毕业论文致谢:求学22载,计算机终成一生的事业与希望...
  17. python爬虫高级教程,JS逆向之百度翻译
  18. 非线性规划 - 数学建模
  19. 托福要学会多少单词量才能考出比较高的分数?
  20. 2022年湖南省中医助理医师考试考前模拟题

热门文章

  1. MySql error 1010 无法删除数据库
  2. Spring Cloud:查看注册到Eureka上的应用信息
  3. 面对对象课程设计报告java,面向对象编程 JAVA编程综合实验报告.doc
  4. 4g网络什么时候淘汰_5G时代,4G将淘汰?4G手机会不会像2g,突然失去网络
  5. matlab程序设计实践,MATLAB程序设计实践(第二题)
  6. mybatis没有clob类型_mybatis将Oracle的Clob类型转成String的方法
  7. des解密 given final_人设不能崩[无限]作者:条纹花瓶(无限流+解密+闯关+直播+爽文)...
  8. c3p0 高并发mysql 连接sleep情况
  9. 分享3个干货满满的Python实战项目,点赞收藏
  10. 万字综述,核心开发者全面解读PyTorch内部机制