delete [] p问题请教

koko1998 2008-03-04 09:12:43
内存越界(写)操作后,内存释放时出现异常,就是堆被破坏了。
具个简单的例子,便于理解。

#include <string.h>
int main()
{
char* pDest = new char[3]();//分配空间 3个字节大小
strcpy(pDest, "123");//将4个字节大小的内存拷贝到3个字节大小空间中,内存越界写
delete [] pDest;// 原分配的3字节大小空间释放 异常出现
pDest = NULL;
return 0;
}


出现异常并不是坏事,可以说能帮助程序员及时发现问题。
可是,数组指针释放的时候,它是怎么知道被分配的堆被破坏了呢?
简单的跟踪了一下,free的时候retval = HeapFree(_crtheap, 0, pBlock);的返回结果为4,产生了堆被破坏的信息提示。
如果谁知道原理的,给简单说明一下,看看系统是如何做到了。谢谢
...全文
187 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
koko1998 2008-03-04
  • 打赏
  • 举报
回复
谢谢各位,给分
koko1998 2008-03-04
  • 打赏
  • 举报
回复
char* pDest = new char[3]();//分配空间 3个字节大小 //弄个()是咋回事,也许也对的,没见过
-----默认初期化为0
koko1998 2008-03-04
  • 打赏
  • 举报
回复
哈哈,ctrl-F5的话,就不是debug了。出了问题估计就死掉了。
ctrl-F5使用,Debug版本和Release版本都看不出问题。
koko1998 2008-03-04
  • 打赏
  • 举报
回复
自己写的东西自己都不能修改阿,真不友好/。
上面的10byte也是在那里看到的,也可能是12byte,说是其他的,忘记了
sheenl 2008-03-04
  • 打赏
  • 举报
回复
不会吧, 你可能是在编辑器中按f5的吧, ctrl-F5或者直接运行那个release版的exe文件, 应该不会出现异常的
koko1998 2008-03-04
  • 打赏
  • 举报
回复
不是说new的size分配在分配地址之前的10个byte之前纪录的么,怎么感觉才9个byte啊?

不过,不管怎么说,理解大体明白了,先谢谢了
koko1998 2008-03-04
  • 打赏
  • 举报
回复
vs2005 Debug版本和Release版本都会报错
编译器的进步啊。哈哈
sheenl 2008-03-04
  • 打赏
  • 举报
回复
看看会出来什么东西, 有的时候不凑巧,会指到非法地址上, 下面的程序就会崩溃, 呵呵。

int main(void)
{
char *p = new char[3];
strcpy(p, "abcde");
char *a = p-10;
for (int i=0; i<20; ++i)
{
printf("%02x ", *a++);
}


return 0;
}
michney 2008-03-04
  • 打赏
  • 举报
回复
内存分配之后会有结束标志,比如fd f0这样的,
越界之后,把结束标志覆盖了,free时候就会出错

但是在windows平台下,debug版会报错,release不会
p0303230 2008-03-04
  • 打赏
  • 举报
回复
呵呵
sheenl 2008-03-04
  • 打赏
  • 举报
回复
堆上的管理信息, 不同的编译器处理方法就不同, debug/release版本也不同,而且随编译器版本不同也
可能会不同, 就不必深究了吧。 一般这种带保护措施的堆管理, 只会出现在debug版本里, release版一般
不会这么做得。
Seanxiaoxiao 2008-03-04
  • 打赏
  • 举报
回复
头部和尾部都是fence(篱笆),就怕写的东西跨越了这块申请的区域
p0303230 2008-03-04
  • 打赏
  • 举报
回复
ls两位的是正解

学习了

为什么信息要分开有的在头部有的在尾部啊?
Seanxiaoxiao 2008-03-04
  • 打赏
  • 举报
回复
……貌似我回了两次啊……意外
Seanxiaoxiao 2008-03-04
  • 打赏
  • 举报
回复
堆上不但有数据,还有保存有堆大小信息,块号,以及头部尾部的fence
03 00 00 00 01 00 00 00 7d 00 00 00 fd fd fd fd cd cd cd fd fd fd fd
楼主的程序在初始化后,堆区是上面的样子,然后strcpy会把一个fd写掉,但这个fd是一个块结尾的fence
所以在释放后,会检测到fence被破坏,然后就报错
sheenl 2008-03-04
  • 打赏
  • 举报
回复
补充一下, 在大多数的编译器, release版本上, 你上面的代码不会报任何错误, 也不会出现任何异常。
甚至你都很难遇到运行时的异常。
Seanxiaoxiao 2008-03-04
  • 打赏
  • 举报
回复
在堆里面,不仅仅分配了数据,也还加上了size,blockNo,headFence,tailFence等信息
在释放时候,会检查这些信息是否被破坏,楼主的程序,在刚申请时如下
03 00 00 00 01 00 00 00 7d 00 00 00 fd fd fd fd cd cd cd fd fd fd fd,
strcpy会把一个fd写掉,然后释放时可以检查到,所以就报错了
p0303230 2008-03-04
  • 打赏
  • 举报
回复
#include <string.h>
int main()
{
char* pDest = new char[3]();//分配空间 3个字节大小 //弄个()是咋回事,也许也对的,没见过
strcpy(pDest, "123");//将4个字节大小的内存拷贝到3个字节大小空间中,内存越界写
delete [] pDest;// 原分配的3字节大小空间释放 //可能123后面的内存是不允许你操作的,所以嘿嘿
pDest = NULL;
return 0;
}


其他的等高人来解
sheenl 2008-03-04
  • 打赏
  • 举报
回复
debug版本?
C++课程设计-单链表——学生信息管理系统全文共9页,当前为第1页。C++课程设计 单链表——学生信息管理系统 C++课程设计-单链表——学生信息管理系统全文共9页,当前为第1页。 学生信息管理系统设计文档 设计任务描述 为了实现学籍管理的简单化,我们基于Visual C++集成开发环境编写了"学生信息管理系统"软件,该软件适用于所有windows操作系统,面向广大用户,界面简洁,操作简单。此软件主要是实现对学生学籍信息进行系统化的管理,可以对学生基本信息进行添加、删除、查找、修改以及对学生成绩的管理,主要是根据学生的学号及其姓名进行操作的。该软件可以更加方便管理者管理学生学籍信息。 功能需求说明 该系统所需要的功能有:1、链表的建立; 2、学生信息的插入; 3、学生信息的查询; 4、学生信息的输出; 5、学生信息的修改; 6、学生信息的删除; 7、良好的欢迎选择界面。 三、总体方案设计 一、实现任务的方法 1、在欢迎选择界面中,使用Switch 这一选择结构来连接程序的执行和用户的命令; 2、在从学生信息的建立直到删除,都是使用链表的相关知识; 3、在定义学生信息时,建立一个Inform 类;在定义学生课程成绩时,自定义了一个achieve 结构体; 总体结构 C++课程设计-单链表——学生信息管理系统全文共9页,当前为第2页。 C++课程设计-单链表——学生信息管理系统全文共9页,当前为第2页。 三、模块划分 (1)链表的建立。 (2)对链表信息的插入。 (3)对链表信息的查找。 (4)对链表信息的输出。 (5)对链表信息的删除。 (6)对链表信息的修改。 课程成绩信息作为附加信息,穿插于各个模块中。 数据结构说明 一、自定义的数据结构: 1、achieve(课程成绩)用于存放课程成绩信息包括课程数、课程名、成绩、学分、总分和平均分。 2、inform(学生基本信息)用于存放学生基本信息,包括姓名、学号、性别等。 C++课程设计-单链表——学生信息管理系统全文共9页,当前为第3页。3、结点结构-Nodetype,定义了数据域inform和指针域next; C++课程设计-单链表——学生信息管理系统全文共9页,当前为第3页。 二、类 Student 用于存放处理学生信息的各个功能函数,private 成员是链表的头指针。 各模块设计说明 一、建立: 首先:建立一个空链表: Student::Student() {head=new Nodetype; head->next=NULL; 表明这是一个空链表 cout<<"请建立链表\n"; } C++课程设计-单链表——学生信息管理系统全文共9页,当前为第4页。然后建立链表: C++课程设计-单链表——学生信息管理系统全文共9页,当前为第4页。 二、添加:按照学号从小到大的顺序插入: 三、输出:将链表的数据输出,由于上述操作,输出时会按照学号从小到大的顺序输出。 四、查找:利用学号和姓名两种方式进行查找,查找时主要是遍历链表进行判断 while(p!=NULL&&(d==1&&strcmp(input,p->data.num)!=0)""(d==2&&strcmp(input,p->data.name)!=0)) {p=p->next; } //遍历链表查找符合要求的节点 五、删除:利用节点的删除操作,找到链表中第i-1个结点,修改其指向后继的指针: q = p->next; p->next = q->next; delete(q); 六、更改:利用查找的操作,查到后在进行重新输入的操作; 测试情况说明 C++课程设计-单链表——学生信息管理系统全文共9页,当前为第5页。测试一:学生信息的输入和输出都正常,但是查找、删除和修改时都只能对第一个数据进行操作,如下图所示: C++课程设计-单链表——学生信息管理系统全文共9页,当前为第5页。 但是当要进行查找、删除、修改操作时,系统只能对第一个对象进行操作 查看程序时,发现查找函数、删除和修改函数都有个逻辑错误 C++课程设计-单链表——学生信息管理系统全文共9页,当前为第6页。全部修改后,程序的上述错误就没再出现了。 C++课程设计-单链表——学生信息管理系统全文共9页,当前为第6页。 错误二:当提示是否输入课程成绩信息时,输入第一门课程名时,会出现无穷循环 但当输入第一门课程后就会出现下图所示状况: 对于这种状况,我百思不得其解,后来请教其他同学,他告诉我错误在于声明课程成绩信息时出错了 C++课程设计-单链表——学生信息管理系统全文共9页,当前为第7页。应该为二维数组,修改之后,课程成绩输入输出便正常了 C++课程设计-单链表——学生信息管理系统全文共9页,当前为第7页。 错误三:输入学生信息时不按照学号大小顺序,输出结果时也不
MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。 愿景我们的愿景是成为 MyBatis 超好的搭档,就像 魂斗罗 中的 1P、2P,基友搭配,效率翻倍。 特性无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作 我们将通过理论与实操的方式来阐述 MyBatis-Plus 的强大功能,体验和学习MyBatis-Plus技术。

64,282

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧