关于C++ delete 来释放new分配的内存

简介: 一般在C语言中我们使用malloc和free进行内存分配和释放,但是在C++中增加了一个新的 new和delete 操作来进行,按照C++的说法delete是释放内存但是指针得到保留,防止内存 泄露,并且NEW和DELETE要成对出现。
一般在C语言中我们使用malloc和free进行内存分配和释放,但是在C++中增加了一个新的
new和delete 操作来进行,按照C++的说法delete是释放内存但是指针得到保留,防止内存
泄露,并且NEW和DELETE要成对出现。我们知道指针本生也是一个保存在内存中某个位置的变量,
如果释放了内存我们是否可以考虑为其中的值得到了删除,而指针自身可以再次指向其他的值?
而还有一点我们需要明白使用NEW分配的内存是HEAP而变量的赋值是栈,


在OS中我们大概可以理解如下(32位系统为例),我这里的共享是指线程是否共享:


4G
     kernel --内核内存
3G   text --代码文本 共享
     data --初始化的全局变量和静态变量 共享
     dss  --未始化的全局变量和静态变量 共享
     栈   --级动态变量数组等 不共享
     堆   --malloc 共享
0    共享库 --库文件 mmap 映射 共享


可以看到栈和堆不是一个区域,并且栈始终是自我释放的遵循后入先出原则


我们接下来用如下的小程序带上GDB进行调试


  8 #include
  9 using namespace std;
 10 
 11 
 12 int main(void)
 13 {
 14     int *p;  //一个不初始化的指针,不能使用*p=一个INT数字,只能赋予一个指针变量p=(init *)0x130000表示p指针指向130000位置
 15     short *b  = new short;
 16     short *c = new short;
 17 
 18     *b=0X128;
 19 
 20     cout<<"noinit int address is :"<< p <<" "<<sizeof(*p)<<endl;
 21     cout<<"short b address is :"<< b <<" "<<sizeof(*b)<<"\n";
 22     cout<<"short c address is :"<< c <<" "<<sizeof(*c)<<endl;
 23     delete b; //成对出现
 24     delete c;
 25     //DELETE不释放指针只是释放内存,那么指针指向的内存可以用于其他用途
 26     cout<<"init int address is :"<< b <<" "<<sizeof(*b)<<"\n";
 27     cout<<"noinit dou address is :"<< c <<" "<<sizeof(*c)<<endl;
 28 
 29     *b=0X256; //直接赋予值,赋值成功
 31     delete b; //不成对出现
 32     *b=0X512; //便于观察而已
 33     delete b; //便于观察,避免指针释放  
  }
~ 如果我们在
 23     delete b;      
 后去GDB *b的只为0那么说明delete起到了效果             
 gdb ./a.out 
(gdb) b 23
Breakpoint 1 at 0x400a79: file pointer2.cpp, line 23.
(gdb) r


Breakpoint 1, main () at pointer2.cpp:23
23              delete b;
(gdb) p b
$1 = (short *) 0x602010
(gdb) x/2xh 0x602010 
0x602010:       0x0128  0x0000
可以看到当前为0X0128数据在这个存储2个字节里面我是也就是0x602010 0x602011
(gdb) n
24          delete c;
(gdb) x/2xh 0x602010
0x602010:       0x0000  0x0000
这里跑完了delete b;  可以看到数据没有了在内存中,继续
继续向下


29              *b=0X256;
(gdb) n
30          delete b;
(gdb) p b
$3 = (short *) 0x602010
这里跑完了 *b=0X256;但是指针位置没有变化,也就是DELETE后指针得到了保留
继续
(gdb) p *b
$4 = 598
(gdb) x/2xh 0x602010
0x602010:       0x0256  0x0000


可以看到数据没有问题。继续看看是否能DELETE
(gdb) n
(gdb) x/2xh 0x602010
0x602010:       0x2020  0x0060
可以看到delete并没有删除数据而已弄了一些垃圾数据进来。
其实这个程序直接跑会报错
*** Error in `./a.out': double free or corruption (fasttop): 0x0000000000f1f010 ***
Aborted (core dumped)
用GDB只是为了找到原因


所以我们必须new和delete 成对使用,否者结果是不确定的,对空指针delete是安全的
delete后指针是得到了保留的没有问题,如果是动态数组将不能使用sizeof来确定他的长度
指针我感觉是使用的栈,同时在函数结束时自我释放。


附带关于GDB的内存查看
转自:http://www.cnblogs.com/super119/archive/2011/03/26/1996125.html


格式: x /nfu


说明
x 是 examine 的缩写


n表示要显示的内存单元的个数


f表示显示方式, 可取如下值
x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。
i 指令地址格式
c 按字符格式显示变量。
f 按浮点数格式显示变量。


u表示一个地址单元的长度
b表示单字节,
h表示双字节,
w表示四字节,
g表示八字节




Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal),
t(binary), f(float), a(address), i(instruction), c(char) and s(string).
Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes)


举例
x/3xh buf
表示从内存地址buf读取内容,
h表示以双字节为一个单位,
3表示三个单位,
x表示按十六进制显示


</sizeof(*c)<<endl;
</sizeof(*b)<<"\n";
</sizeof(*c)<<endl;
</sizeof(*b)<<"\n";
</sizeof(*p)<<endl;
相关实践学习
阿里云图数据库GDB入门与应用
图数据库(Graph Database,简称GDB)是一种支持Property Graph图模型、用于处理高度连接数据查询与存储的实时、可靠的在线数据库服务。它支持Apache TinkerPop Gremlin查询语言,可以帮您快速构建基于高度连接的数据集的应用程序。GDB非常适合社交网络、欺诈检测、推荐引擎、实时图谱、网络/IT运营这类高度互连数据集的场景。 GDB由阿里云自主研发,具备如下优势: 标准图查询语言:支持属性图,高度兼容Gremlin图查询语言。 高度优化的自研引擎:高度优化的自研图计算层和存储层,云盘多副本保障数据超高可靠,支持ACID事务。 服务高可用:支持高可用实例,节点故障迅速转移,保障业务连续性。 易运维:提供备份恢复、自动升级、监控告警、故障切换等丰富的运维功能,大幅降低运维成本。 产品主页:https://www.aliyun.com/product/gdb
相关文章
|
5月前
|
安全 C语言 C++
比较C++的内存分配与管理方式new/delete与C语言中的malloc/realloc/calloc/free。
在实用性方面,C++的内存管理方式提供了面向对象的特性,它是处理构造和析构、需要类型安全和异常处理的首选方案。而C语言的内存管理函数适用于简单的内存分配,例如分配原始内存块或复杂性较低的数据结构,没有构造和析构的要求。当从C迁移到C++,或在C++中使用C代码时,了解两种内存管理方式的差异非常重要。
200 26
|
6月前
|
C语言 C++
c与c++的内存管理
再比如还有这样的分组: 这种分组是最正确的给出内存四个分区名字:栈区、堆区、全局区(俗话也叫静态变量区)、代码区(也叫代码段)(代码段又分很多种,比如常量区)当然也会看到别的定义如:两者都正确,记那个都选,我选择的是第一个。再比如还有这样的分组: 这种分组是最正确的答案分别是 C C C A A A A A D A B。
118 1
|
9月前
|
存储 Linux C语言
C++/C的内存管理
本文主要讲解C++/C中的程序区域划分与内存管理方式。首先介绍程序区域,包括栈(存储局部变量等,向下增长)、堆(动态内存分配,向上分配)、数据段(存储静态和全局变量)及代码段(存放可执行代码)。接着探讨C++内存管理,new/delete操作符相比C语言的malloc/free更强大,支持对象构造与析构。还深入解析了new/delete的实现原理、定位new表达式以及二者与malloc/free的区别。最后附上一句鸡汤激励大家行动缓解焦虑。
|
10月前
|
安全 C语言 C++
彻底摘明白 C++ 的动态内存分配原理
大家好,我是V哥。C++的动态内存分配允许程序在运行时请求和释放内存,主要通过`new`/`delete`(用于对象)及`malloc`/`calloc`/`realloc`/`free`(继承自C语言)实现。`new`分配并初始化对象内存,`delete`释放并调用析构函数;而`malloc`等函数仅处理裸内存,不涉及构造与析构。掌握这些可有效管理内存,避免泄漏和悬空指针问题。智能指针如`std::unique_ptr`和`std::shared_ptr`能自动管理内存,确保异常安全。关注威哥爱编程,了解更多全栈开发技巧。 先赞再看后评论,腰缠万贯财进门。
452 0
|
10月前
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
6月前
|
人工智能 机器人 编译器
c++模板初阶----函数模板与类模板
class 类模板名private://类内成员声明class Apublic:A(T val):a(val){}private:T a;return 0;运行结果:注意:类模板中的成员函数若是放在类外定义时,需要加模板参数列表。return 0;
174 0
|
6月前
|
存储 编译器 程序员
c++的类(附含explicit关键字,友元,内部类)
本文介绍了C++中类的核心概念与用法,涵盖封装、继承、多态三大特性。重点讲解了类的定义(`class`与`struct`)、访问限定符(`private`、`public`、`protected`)、类的作用域及成员函数的声明与定义分离。同时深入探讨了类的大小计算、`this`指针、默认成员函数(构造函数、析构函数、拷贝构造、赋值重载)以及运算符重载等内容。 文章还详细分析了`explicit`关键字的作用、静态成员(变量与函数)、友元(友元函数与友元类)的概念及其使用场景,并简要介绍了内部类的特性。
265 0
|
8月前
|
编译器 C++ 容器
【c++11】c++11新特性(上)(列表初始化、右值引用和移动语义、类的新默认成员函数、lambda表达式)
C++11为C++带来了革命性变化,引入了列表初始化、右值引用、移动语义、类的新默认成员函数和lambda表达式等特性。列表初始化统一了对象初始化方式,initializer_list简化了容器多元素初始化;右值引用和移动语义优化了资源管理,减少拷贝开销;类新增移动构造和移动赋值函数提升性能;lambda表达式提供匿名函数对象,增强代码简洁性和灵活性。这些特性共同推动了现代C++编程的发展,提升了开发效率与程序性能。
304 12
|
9月前
|
设计模式 安全 C++
【C++进阶】特殊类设计 && 单例模式
通过对特殊类设计和单例模式的深入探讨,我们可以更好地设计和实现复杂的C++程序。特殊类设计提高了代码的安全性和可维护性,而单例模式则确保类的唯一实例性和全局访问性。理解并掌握这些高级设计技巧,对于提升C++编程水平至关重要。
180 16
|
10月前
|
编译器 C语言 C++
类和对象的简述(c++篇)
类和对象的简述(c++篇)

热门文章

最新文章