delete释放new[] 以及 delete[]释放new 的问题

2023-05-16

同花顺的笔试过程中遇到这么一个类似问题:

A* ptr = new A[10];
for(int i = 0;i < n;i++){
    delete &ptr[i];
}

由此衍生出两个问题:

  1. new[] 申请的空间用delete释放会发生什么
  2. new 申请的空间用delete[] 释放会发生什么

下面就让我们来探索一下其中的奥秘

一.new[]申请的空间用delete释放

1.内置类型

如int,char,float,double等内置类型这样操作是没有什么问题的.

int main() {
    //以内置类型int为例:
	int* ptr = new int[10];
	delete ptr;
	return 0;
}

如上代码,在执行delete ptr之后,可以看到这一片连续的空间被释放.

2.自定义类型

如c语言中的结构体,枚举,联合体,C++中的类.自定义类型这样操作是有问题的.

class A {
public:
	int _sum;
	~A() {
		cout << "调用析构" << endl;
	}
};
int main() {
	A* ptr = new A[10];
	delete ptr;
	return 0;
}

 执行delete ptr时程序,只输出了一句"调用析构",便异常终止了.

原理:

new/new[] 和 delete/delete[]的原理: new和delete在底层实际是分别封装了operator new 和 operator delete两个全局函数,而operator new 和 operatordelete 在底层又分别封装了malloc() 和 free().

内置类型为何不会出错:

以上面代码中的内置类型int为例,new int[10]时底层实际是malloc申请了10个int类型数据的空间(也就是40字节).当delete时,最底层用free直接释放,显然是没有问题的.

自定义类型为何会出错:

以上面代码中的类A为例,new A[10]时,与int的处理方式不同.

对于自定义类型,new在最底层用malloc申请空间后,会调用类A的构造函数,对每个元素进行初始化等操作.

这里需要注意的是 当new[] 分配的类型时自定义类型时,new[]会让malloc在分配空间时多申请4字节,new[]返回的是底层malloc返回地址向后偏移4字节的地址.如下图所示:

具体到new int[10]时,malloc本应该申请10个A类型大小的空间,也就是40个字节,但是此时malloc实际上申请了44个字节,new返回的指针是malloc返回的指针向后偏移4个字节的地址.

这4个字节存放着所申请自定义元素的个数.

那么前面说free自己可以通过传入一个指针就知道释放多大的空间,那么增加这4个字节来存放元素个数岂不是多次一举?

很有必要讲一下delete[]的原理: delete[]会把new[]所返回的指针向前偏移4个字节的地址返回给free,因此free就能正确的释放掉整片空间.

A* ptr = new A[10]的正确搭配是delete[] ptr,那么delete[]此时获取到的指针是new[]的返回值(并不是malloc所申请空间的首地址),这样的话底层的free并不能通过这个指针释放掉这片空间,但是delete[]hi把new所返回的指针向前偏移4个字节位置的地址给free.

多出来4个字节保存着自定义元素的个数的作用:

一个对象在释放空间前需要调用析构函数来完成一些资源的清理工作.那么问题来了,delete[] 没有像new A[10]传参进去,delete[]怎么知道调用多少次析构.

其实多出来的4个字节存的元素个数,就是用来让delete[]知道调用多少次析构函数的.

了解完delete[]的原理,再回到上面代码具体出错的原因.

new出来的10个对象,执行delete ptr时,先调用一次析构函数完成对第一个对象的析构,后面9个都不会析构,因为delete对应的new都是单个元素的操作(new返回的是malloc返回的指针,delete也只调用一次析构),而此时的ptr并不是malloc返回的首地址,所有delete在底层调用free时,给free传入了一个free无法识别的指针,程序就会崩溃.(因此上面的程序运行后只打印了一次调用析构就崩溃了)

小结:

  1. new[]在给自定义类型空间时,会多分配4个字节用来存储元素个数.通过*(int*)(ptr-1)就能看到或者直接查看内存也可以看到.所以delete用此时new[]返回的指针来调用自己底层的free时,free就出错了,程序就会崩溃.
  2. new[]在给内置类型申请空间时,不会存储元素个数,因为自定义类型delete[]时没有析构函数可调用(所以没必要存储),free不会出错

二.new申请的空间用delete[]释放

1.内置类型

当类型是内置类型时,delete[]和delete一样,所以不会出现问题.

int main() {
	int* ptr = new int();
	delete[] ptr;
 	return 0;
}

2.自定义类型

会出现错误, 原因是也是前面讲过了, 当类型是自定义类型时 delete[ ] p 会先根据p前面4字节中的元素个数来确定调用析构函数的次数,

先到用析构函数, 前四个字节的内存是非法内存, 其中的值是随机的, 所以说调用析构次数也是随机的, 通常这个数很大, 所以会调用很多次析构, 再把接收的指针p往前4字节的地址给底层的free(注意, 往前4字节, 这四字节是没有被申请的空间).

由于free不能释放没有被申请的空间, 所以free出错, 而且free也不能通过这个p往前4字节的地址知晓到底释放多大的空间, 也会出错 (free只能通过malloc返回的地址知道要释放多大空间).

class A {
public:
	int _sum;
	~A() {
		cout << "调用析构" << endl;
	}
};
int main() {
	A* ptr = new A();
	delete[] ptr;
 	return 0;
}

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

delete释放new[] 以及 delete[]释放new 的问题 的相关文章

  • Java—内部类

    It s possible to please a class definition within another class definition 内部类即定义在另一个类的内部的类 When you create an inner cla
  • JavaScript undefined 属性

    定义和用法 undefined 属性用于存放 JavaScript 的 undefined 值 语法 undefined 说明 无法使用 for in 循环来枚举 undefined 属性 也不能用 delete 运算符来删除它 undef
  • Treap树实现文件C语言

    对于这个 想说的是 关于 NullNode 结点 在调用Release 释放内存之后 要将其恢复为NULL 以便下次的连续使用 自己想到的 很不错 treap c treap树实现文件 include treapTree h 全局变量声明定
  • 私有构造函数

    通常我们都将构造函数的声明置于public区段 假如我们将其放入private区段中会发生什么样的后果 没错 我也知道这将会使构造函数成为私有的 这意味着什么 我们知道 当我们在程序中声明一个对象时 编译器为调用构造函数 如果有的话 而这个
  • 基数排序比快速排序快

    最近在关于算法的书籍 本以为以前看过的算法书都说快速排序是最好的排序算法 也没有想过 闲着无聊变写了一个关于基数排序的算法简单分析了一下应该时间复杂度比快速排序 小 于是编程实现果然结果要比快速排序 快 对两者都 1000000个数排序快速
  • virtual,override,new ,extern,abstract修饰符

    方法定义中可以使用的修饰符有 a new b public c protected d internal e private f static g virtual h override i extern j abstract 对于virtu
  • ASCII表

    http office microsoft com zh cn assistance HA011331362052 aspx ASCII 打印字符 数字 32 126 分配给了能在键盘上找到的字符 当您查看或打印文档时就会出现 数字 127
  • C++深拷贝和浅拷贝

    C 深拷贝 浅拷贝 对于普通类型的对象来说 它们之间的复制是很简单的 例如 int a 88 int b a 而类对象与普通对象不同 类对象内部结构一般较为复杂 存在各种成员变量 下面看一个类对象拷贝的简单例子 include
  • 复制文件夹所有内容 和 删除整个文件夹的2个函数

    选择自 hycapril 的 Blog 实现一个静态方法将指定文件夹下面的所有内容copy到目标文件夹下面 如果目标文件夹为只读属性就会报错 April 18April2005 In STU public static void CopyD
  • 结构体指针数组 内存分配 释放

    include
  • 查询及删除重复记录

    查询及删除重复记录的方法大全 1 查找表中多余的重复记录 重复记录是根据单个字段 peopleId 来判断select from peoplewhere peopleId in select peopleId from people gro
  • VC 根据域名获取IP

    include Winsock2 h pragma comment lib Ws2 32 lib 注意字符串需以 0结尾 例如 lpzSeverName www baidu com 0 bool WINAPI Domain2IP char
  • Haxe: class, object, new and constructor

    haxe 类 对象 new 和 构造函数 package if neko import neko Lib import neko io File end class Thing public function new trace new f
  • Xcode 4 常用快捷键(和 Xcode 3 有些不一样了)

    Xcode 4 常用快捷键 和 Xcode 3 有些不一样了 2011 06 16 Unmi 把 Xcode 由 3 2 5 升级到 Xcode 4 0 2 之后 满以为快捷键总该不会变化太大吧 没想又要经历一个快捷键的适应过程 发现有些在
  • 指针的删除

    1 在链表中 将某个指针delete 指向该指针的那个指针的next 不会自动赋值为NULL 需要手动赋值 2 删掉 某指针所指向的内存 该指针仍然可以使用 下面是一个带头指针的单向链表 void Stack Pop int value i
  • 关于C++对象模型(下)

    下篇主要讨论调用成员函数 访问成员变量的开销 及其特殊成员函数 数组 异常处理的讨论 这篇文章中出现的对象定义都出现在上篇中 全文在这里下载 文章内容转自 http tb blog csdn net TrackBack aspx PostI
  • 20个常见的Java错误以及规避方法

    原文 50 Common Java Errors and How to Avoid Them Part 1 作者 Angela Stringfellow 翻译 雁惊寒 译者注 本文介绍了20个常见的Java编译器错误 每种错误都包含了代码片
  • delete 和 delete []的真正区别

    c 中对new申请的内存的释放方式有delete和delete 两种方式 到底这两者有什么区别呢 1 我们通常从教科书上看到这样的说明 delete 释放new分配的单个对象指针指向的内存 delete 释放new分配的对象数组指针指向的内
  • delete LEFT JOIN 的一个问题解决办法

    LEFT JOIN 的一个问题解决办法 今天在一个程序后台删除一个东西的时候 却出现了这个问题 Java代码 System Message MySQL Query Error User admin Time 2007 10 20 21 08
  • C++ primer智能指针(HasPtr)实现

    智能指针显然是C 吸引人的地方之一 必须掌握 看了 C primer 里面着重讲了智能指针的实现方式 书中说到 HasPtr 注 就是自定义的智能指针 在其它方面的行为与普通指针一致 具体而言 复制对象时 副本和原对象将指向同一基础对象 如

随机推荐

  • unity 3D:自动寻路

    首先 xff0c 搭建一下场景 xff0c 场景要求 xff1a 有遮挡 xff0c 设置好不可走区域为navigation static 以及 not walkable 在人身上添加Nav Mesh Agent 设置好后勾选显示导航网格
  • Java高级特性反射与动态代理模式

    文章目录 前言一 了解反射二 继续了解反射 xff08 哈哈哈 xff09 1 每一个类对应的class放在哪里 xff1f 2 这个class里面都保存了什么3 如何使用 xff1f 3 1 获取类加载器3 2 获取构造器对象3 3 获取
  • Unity3D 使用SceneManager跳转/加载场景

    很久没有更新博客了 xff0c 最近也是还在学习U3D 下面写一下使用SceneManager跳转 加载场景 我们假设要点击一个按钮跳转 xff0c 那么我们只要把跳转的代码写进按钮点击事件里就好了 其实加载场景很简单 xff0c 只需要写
  • Hisat2 Bowtie2比对结果解读

    Bowtie的中文意思是 xff1a 领结 xff0c 蝴蝶结 Bowtie2用户手册 xff1a http bowtie bio sourceforge net bowtie2 manual shtml 在看比对结果前需要了解三个概念 x
  • React 项目启动报错:The “path” argument must be of type string

    今天下载一个旧的React项目 xff0c yarn start 运行 xff0c 报错 xff1a TypeError ERR INVALID ARG TYPE The path argument must be of type stri
  • Android 身份认证基本概念

    身份验证 Android 采用通过用户身份验证把关的加密密钥机制 xff0c 该机制需要以下组件 xff1a 加密密钥存储和服务提供程序 存储加密密钥并基于这些密钥提供标准加密例程 Android 支持由硬件支持的密钥库和 Keymaste
  • Gnome增加消息提醒extension 适用于聊天工具如xchat "message notifier" "notifications alert" "permanent notification&quo

    使用如xchat这样的聊天工具 xff0c 有人跟你说话时 xff0c 在KDE桌面中 xff0c 默认系统托盘中的xchat托盘会闪烁 xff0c 直到你点击将xchat切换到前台 xff0c 这是xchat在preference可以设置
  • 读取文件报错:FileNotFoundError: [Errno 2] No such file or directory

    文章目录 问题描述问题分析解决办法 问题描述 使用 img 61 Image open 39 data DSC 8923 jpg 39 读取一张图片时 xff0c 报 FileNotFoundError Errno 2 No such fi
  • CentOS7离线安装图像化界面踩坑及脱坑历程

    CentOS7离线安装图像化界面 背景安装问题尝试一 xff1a 尝试二 xff1a 其他问题总结 背景 很久之前实验室的一台服务器安装了CentOS 7 6 1810版本的linux系统 xff0c 然而当时安装系统的同学不知出于什么目的
  • Eslint 配置及规则说明

    中文官方网站 基本使用教程 安装 可以全局安装 xff0c 也可以在项目下面安装 如下是在项目中安装示例 xff0c 只需要在 package json 中添加如下配置 xff0c 并进行安装 xff1a gt 34 eslint 34 3
  • Ubuntu自动登录图形系统界面(免密码、开机自启动)

    Ubuntu自动登录图形系统界面 xff08 免密码 开机自启动 xff09 操作系统版本 xff1a 18 04 修改50 unity greeter conf xff0c 使其允许root登录 span class token func
  • 学C++有多难,你知道吗?

    都2020年了 xff0c 还要学C 43 43 吗 xff1f C 43 43 好多理工科大学里面都有 xff0c 它的学习难度比其他编程语言比如Python Javascript 和Java等等难 那为什么呢 xff1f C 43 43
  • 搞懂Java高级特性--注解

    1 注解是什么 xff1f Java注解 xff08 Annotation xff09 又称Java标注 xff0c 是JDK5 0引入的一种注释机制 xff0c 注解是元数据的一种形式 xff0c 提供有关于程序但不属于程序本身的数据 x
  • 为什么都说代码改变世界?是因为这五位程序员创造了未来!

    致敬那些为软件开发奠定坚实基础的计算机科学先驱 从 1 和 0 开始 xff0c 编程经历了很长一段路 xff0c 才达到了现在的抽象状态 过去的程序员用伟大的发明 xff0c 为现代程序员轻松地完成工作奠定了坚实的基础 如果我们研究某个软
  • 编译提示缺少libjli.so,jar command not found,javadoc错误等

    这周一周忙于Ubuntu server环境下的Android编译环境的搭建 xff0c 由于刚开始真正使用Linux xff0c xff08 以前虽然用过Ubuntu xff0c 但是就当win用了 就这样还没坚持下来 xff0c 现在工作
  • 银河麒麟系统4.0.2离线安装MySQL教程

    银河麒麟系统4 0 2离线安装MySQL教程 xff08 Ubuntu离线安装MySQL教程 xff09 https www jianshu com p 478dc7c9b9e0 这个教程很详细 xff0c 我不再多说 xff0c 而且亲测
  • 实现线程同步的几种方式

    在多线程中线程的执行顺序是依靠哪个线程先获得到CUP的执行权谁就先执行 xff0c 虽然说可以通过线程的优先权进行设置 xff0c 但是他只是获取CUP执行权的概率高点 xff0c 但是也不一定必须先执行 在这种情况下如何保证线程按照一定的
  • STC开天斧虚拟示波器使用

    开天斧外观图 xff0c 颜值非常可以 1 在keil中添加STC8H8K64U的型号和头文件 xff0c 添加功能在STC IPS软件里 首先点击Keil仿真设置 xff0c 然后选择单片机型号STC8H8K64U xff0c 然后点击添
  • android AlertDialog 弹窗自定义布局 点击外部不关闭弹窗

    AlertDialog span class token punctuation span Builder builder span class token operator 61 span span class token keyword
  • delete释放new[] 以及 delete[]释放new 的问题

    在同花顺 的笔试过程中遇到这么一个类似问题 A ptr 61 new A 10 for int i 61 0 i lt n i 43 43 delete amp ptr i 由此衍生出两个问题 new 申请的空间用delete释放会发生什么