c++ new delete 常踩的坑

WeTest 导读

c++ 是公司开发最常用的语言之一, 那New和Delete 这两个函数是所有开发者即爱又恨的函数。由new 和delete引发的bug , coredump , 让多少程序员加了多少班。



一、遇到的问题

C++ 中,你也许经常使用 new 和 delete 来动态申请和

● 释放内存,但你可曾想过以下问题呢?

● new 和 delete 是函数吗?

● new [] 和 delete [] 又是什么?什么时候用它们?

● 你知道 operator new 和 operator delete 吗?

为什么 new [] 出来的数组有时可以用 delete 释放有时又不行?

二、发现的代码 

有时看到代码是这么写的:

这样有问题吗 ?    在服务器上长期运行,会引起内存泄漏吗?

写了个测试程序, 看看这些都是神马。

程序运行结果:

注意这里多出来的 4字节

 

三、总结

这个问题直接导致我们需要在 new [] 一个对象数组时,需要保存数组的维度,C++ 的做法是在分配数组空间时多分配了 4 个字节的大小,专门保存数组的大小,

在 delete [] 时就可以取出这个保存的数,就知道了需要调用析构函数多少次了。

四、c++对象内存分配与释放

有人提出两个问题:

1、那个4字节在 delete [] , 是怎么跳过的。

2、free 是怎么知道自己的长度。

以下写几个栗子 看一下:

delete 对象  :

部分汇编码如下:

delete复杂数据类型先调用析构函数再调用operator delete。

c++的内存分配    

看一下 M$ 编译器是如何构造和释放内存的

小的总结 

内存分配一般有两种方式: 
1 非入侵式,内存分配器自行先申请内存(和栈配合使用),用作记录用户层的申请记录(地址,大小)。 用户释放空间时会查找该表,除了知道释放空间大小外还能判断该指针是合法。

2 入侵式,例如用户要申请1byte的内存,而内存分配器会分配5byte的空间(32位),前面4byte用于申请的大小。释放内存时会先向前偏移4个byte找到申请大小,再进行释放。

两种方法各有优缺点,第一种安全,但慢。第二种快但对程序员的指针控制能力要求更高,稍有不慎越界了会对空间信息做成破坏。

绝大多数的分配器会采用第一种方式实现,而操作系统级的分配器采用了虚拟等方式,可能要记录更多信息。

五、最后分析自定义数组类型 

那么数组的分配和释放是 怎么自动的 增加 4 字节 和 减 4字节的呢?

实在不想看了 ,贴一点 关键的吧 , New 对象的部分汇编

上面的汇编码流程大致是:

1、调用operator new分配堆空间

2、调用构造代理函数构造堆对象,在调用构造代理函数时,通过压栈,像其传递了5个参数,分别是 a)第一个堆对象首地址 b)堆对象大小c)堆对象个数 d)构造函数地址 e)析构函数地址

3、传回第一个堆对象首地址,而不是申请到的堆空间首地址

析构的部分代码

看看析构函数是如何自动偏移4字节的。

以上的汇编似乎没有涉及 4字节的偏移 , 那看看  vector deleting destructor 这个函数干了啥

看到  operator delete[] (0341244h) 这个函数了 , 前面将 对象首地址 -4  ,然后释放内存, 现在知道为啥 析构偏移4字节了吧



 关于腾讯WeTest (wetest.qq.com)

腾讯WeTest是腾讯游戏官方推出的一站式游戏测试平台,用十年腾讯游戏测试经验帮助广大开发者对游戏开发全生命周期进行质量保障。腾讯WeTest提供:适配兼容测试;云端真机调试;安全测试;耗电量测试;服务器性能测试;舆情分析等服务。

点击地址:http://wetest.qq.com/立即体验!

时间: 2024-10-13 12:13:38

c++ new delete 常踩的坑的相关文章

初用react容易踩的坑

此文章同步连接: https://github.com/p2227/p2227.github.io/issues/3 # 初用react容易踩的坑 ## 自定义组件忘记大写第一个字母 ```javascript var myComp = React.createClass({ render: function() { return <div>Hello world</div>; } }); ReactDOM.render(<myComp />, mountNode);

Ubuntu中安装FTP 服务器自己踩得坑

12点多了,擦!做个码农真不容易呀! 系统:Ubuntu16.04 安装:FTP 步骤: 1.不管有没有一上来我先卸载: sudo apt-get purge vsftpd 2.再安装:sudo apt-get install vsftpd 3.创建ftp用户: 创建用户目录 sudo mkdir /home/uftp 创建用户 sudo useradd -d /home/uftp -s /bin/bash uftp 修改密码 sudo passwd uftp#这里会提示你输入二次密码 4配置v

使用CCNode作为容器容易踩的坑

Cocos2dx中CCNode经常作为一个父容器,里面装一些UI控件,最后组成一个复杂的自定义的UI控件,但是在使用别人的自定义控件和自己写自定义问题的时候会踩一些坑. 首先拿到一个自定义的UI控件一定要明确他的position是在控件的什么位置,即锚点位置,这样才能知道改如何取设置position. 其次知道父容器区域是不是全包含子容器的,因为ccnode里面的子节点的范围是可以超出你设定的ccnode的区域的.原因在于ccnode可以没有区域,这个跟winform桌面编程的Panel有差别,

踩一坑,采一金之php数据类型那点“破”事

学海无涯,乘舟以渡之~ php边学边写差不多一年多点,php这种弱类型语言与之前接触的c.java.as3等语言还是挺不一样的,现在觉得很庆幸的是从c开始学编程,无论数据类型还是指针也好,至少有个基础的概念. 在php数据类型上踩了不少坑,也学到了一些东西,在这里分享一下,看源码可能会很枯燥,不过了解一些底层实现就好,后面不要再踩坑. 序. 之前在网上看到有比较热的帖子说:PHP的ip2long有bug,请慎用?于是看了下描述,大致如下 <?php echo ip2long('58.99.11.

Asp.Net Core中使用Swagger,你不得不踩的坑

很久不来写blog了,换了新工作后很累,很忙.每天常态化加班到21点,偶尔还会到凌晨,加班很累,但这段时间,也确实学到了不少知识,今天这篇文章和大家分享一下:Asp.Net Core中使用Swagger,你不得不踩的坑. 这篇文章着重讲几点: swagger 跨层注释问题 swagger Get请求传多个参数的问题 swagger Enum 注释问题 swagger api文档版本控制 第一步:搭建一个webapi项目或者mvc项目,引入swagger nuget 我创建项目,习惯性的先创建一个

必读丨新手程序员最容易踩的“坑”,你踩过几个?

人生,就是一边踩"坑",一边上升的过程.而程序员的一生,不仅要改无数的BUG,也要越过很多的"坑".今天,小千为大家分享一些开发人员常见的"坑",希望同学们能够从中受益. 1.重新实现API中已有的代码 大多数开发人员都会利用某种框架来减轻工作的负担.对于没有使用该框架经验的开发人员来说,掌握框架的API提供的所有功能非常困难. 因此,他们常常会重新实现API中已有的某些代码.没有经验的开发人员更有可能踩这个坑的原因有两个:? 第一,由于缺乏经验

mobile web曾经的踩过坑

兼容性一直是前端工程师心中永远的痛.手机浏览器,因为基本是webkit(blink)内核当道,很多公司,不用考虑IE系的浏览器,所以感觉兼容性上的问题可能会少一些. 但是手机端,虽然出了很多工具,但是调试依然比PC端麻烦很多.而且很多坑是因为手机浏览器本身的bug,一旦出现,相应的解决方案很难根据以前的经验进行推测.只能寄希望于谷歌 + 猜. 这里记录一下我做手机端浏览器曾经踩过的坑.之所以用”曾经”,随着版本的更新,有些问题没了. 另外我(我司)没有足够的人力和物力对很多手机浏览器进行测试,我

Markdown编辑器开发记录(一):开发的初衷和初期踩的坑

先说下选择Markdown编辑器的原因,我们进行平台开发,需要很多的操作手册和API文档,要在网站中展示出来就需要是HTML格式的文件,但是由于内容很多,不可能全部由技术人员进行文档的编写,如果是只有文档操作经验的人来做就会出现很麻烦的情况. 最初,我们先用试着用word来写,再转换成HTML文件保存,但是这样存在几个问题:1.转换出来的文件标签和样式十分的杂乱和冗余,有太多无用的标签,后期要修改样式也十分不容易:2.图片无法保存,在word文档中插入的图片路径是固定的物理路径,或是与文档一起存

redhat 7.2更新yum源时踩的坑

一.update yum 1.先查看redhat7.2中yum的包版本 [[email protected] jiayimeng]#  rpm -qa | grep yum yum-rhn-plugin-2.0.1-5.el7.noarch yum-metadata-parser-1.1.4-10.el7.x86_64 yum-langpacks-0.4.2-4.el7.noarch yum-utils-1.1.31-34.el7.noarch yum-3.4.3-132.el7.noarch