360面试题,delete/delete[]/free如何知道该释放多少内存?

NBTestNC 2013-11-15 10:09:57
如题,delete/delete[]/free如何知道该释放多少内存呢?
有人说是在new的时候额外在内存开始处添加了额外的内存记录大小,但我们知道:

char a = 'a';
char * p1 = new char[10];
char * p2 = &a;

p1,p2是一样的指针,如果在开始处加入额外的信息化,p2指针如何能正常运行?
还是有个诸如map表的东西记录new的地址对应的内存大小,delete的时候去查询然后删除?
...全文
786 28 打赏 收藏 转发到动态 举报
写回复
用AI写文章
28 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
win32平台的下这两个函数不是间接调用HeapAlloc和HeapFree的么?
  • 打赏
  • 举报
回复
引用 14 楼 mysatans 的回复:
[quote=引用 9 楼 max_min_ 的回复:] 楼主可以试试 malloc两块内存地址试试!两次地址是不连续的,中间多余的几个字节的地址大小是有一部分来存放free的时候停止的标志位的,
这个在VS DEBUG上,到是见过,我用的VS2013,每个new的内存前面后面都用会用4个0xfd进行分隔,但好像只在DEBUG下才这样,主要是为了对内存的使用情况进行跟踪,但这种停止位不好设置值,因为可能会和用户数据冲突,这个如何解决呢?[/quote] 最简单的办法是前面多减点。不一定非要前4个字节。 弄个地址和长度对应表也很方便。
ccwRadar 2013-11-16
  • 打赏
  • 举报
回复
就是就是,出这样的题目,有点变态
lm_whales 2013-11-16
  • 打赏
  • 举报
回复
这种东西和分配内存的算法实现有关, 用 要 释放的内存做索引,查找 相关的结构就得到内存的大小 free 可以不需要知道内存大小。 delete 也可以不需要知道内存大小。 delete[] 才需要知道内存大小,分配了几个对象。 因为要调用析构函数。 如果,你遇到这个问题,他并不是考你的; 如何搞个统一的,可移植的函数,获取所分配的内存的大小,和对象个数。 而是,考你知不知道,系统内存分配的算法,了解多少! 你知道多少,就回答多少好了; 不然,你可以自己设计一个算法; 告诉考官,可以用这种方式实现内存分配,即可。 最简单的算法 在分配内存的前面一个位置,存储分配的内存大小(或者分配的对象个数) //
void *malloc(int size){
     void *p = find_free_mem(size);
     //find_free_mem 是一个算法,用于查找可以分配size大小内存的内存块
     //。。。。。。 //其他操作,比如设置链表头,这里会移动指针p
     int *plength = p;
     * plength = size;    
    return ++ plength;//返回,记录后面的内存
 }
// 获得分配的内存大小
int getallocsize(void *p){
    int * plength =p;
    return * --plength; 
}
「已注销」 2013-11-16
  • 打赏
  • 举报
回复
估计是考你有没有看过运行库的源码
s271637411 2013-11-16
  • 打赏
  • 举报
回复
malloc分配内存时会分配比实际多点的内存,多余的字节是用来保存申请内存各种信息的附加数据,忘了是几个字节,可以去测试一下。
unituniverse2 2013-11-16
  • 打赏
  • 举报
回复
引用 14 楼 mysatans 的回复:
[quote=引用 9 楼 max_min_ 的回复:] 楼主可以试试 malloc两块内存地址试试!两次地址是不连续的,中间多余的几个字节的地址大小是有一部分来存放free的时候停止的标志位的,
这个在VS DEBUG上,到是见过,我用的VS2013,每个new的内存前面后面都用会用4个0xfd进行分隔,但好像只在DEBUG下才这样,主要是为了对内存的使用情况进行跟踪,但这种停止位不好设置值,因为可能会和用户数据冲突,这个如何解决呢?[/quote] release下面没有这个停止位的。和用户数据冲突更“不可能”,打了引号的意思就是 这些位是为了测试你程序是否溢出的安全位,如果这些地方被改动过,delete的时候就报异常。这些位本来就是正常情况下(意思是如果你的代码没有问题)不该写到的地方。
unituniverse2 2013-11-16
  • 打赏
  • 举报
回复
引用 13 楼 mysatans 的回复:
[quote=引用 6 楼 unituniverse2 的回复:] 严重的依赖于实现的东西。 何况也没有指明什么平台上的什么编译器 有可能根本不标记长度的。就比如简单的信任程序员的代码,删除的时候把已占用的标志改成未占用。因为某些场合长度都是已知的(比如某些涉及到内存池放置固定大小对象的算法)。也可能把长度专门集中起来标记到一个特殊区域里,那个区域还记录了各起始地址。反正根本不和分配的那个地址相邻 现在很多地方出题出的说是C++的但是严重的偏向于自己业务方面(不是说这样做是错误的),比如360这样出题还是基于自己主要是做分析的,研究对象都是别人用已知的编译器编译出来的已知的程序,他自己当然很少考虑什么兼容性可移植性一类的东西。对他们来说未来的东西可能会是什么样等出来了的时候再去研究。
恩,具体的实现确实很依赖细节,但360没有提供明确答案,估计考察的是你对细节的了解,以及你如何提出一个合理的解决办法[/quote] 这是一个没有保证的问题。 细节就是各家有各家的算法,没有个统一的规定的。另外说到“合理的解决方法”,其实就是,如果你是一个合格的C++程序员的话,这种问题你不能去关心。作为兴趣或者自己设计编译器你可以去研究。但是写到代码里去访问那些内部数据结构来实现所谓的“特殊效果”真的就不可取了,因为vc编译出来的程序能工作,gcc编译出来的就不一定了,还有更多其它的编译器等。需要全部抓出来一一针对性的解决也不现实。就算你有那个财力人力,也许以后哪个厂家心血来潮了也设计个编译器呢。 要适当关心的倒是一个小问题,就是内存分配算法是有一定代价的(时间开销和额外的空间开销),并不仅是你程序代码申请了多少就会只消耗申请的那些。所以根据自己程序的实现需要/不需要做适当的针对性优化。
NBTestNC 2013-11-16
  • 打赏
  • 举报
回复
引用 12 楼 henry3695 的回复:
这个是操作系统记录的啊,new delete可以看作是程序和操作系统的交互 指针如何知道是指针,指针所指的内存块的大小,这都记录在操作系统里面吧,我是这么想的不知道对不对 指针占4个字节,就是记录了地址,所指的内存块大小,肯定是有个地方会记录的,猜测是map
这种猜测也是可能的,不管在哪个平台上,程序终究是要调用系统的API,也许在系统的API中帮我们记录了开辟的空间的大小,编译器不用管也是可能的。
NBTestNC 2013-11-16
  • 打赏
  • 举报
回复
引用 9 楼 max_min_ 的回复:
楼主可以试试 malloc两块内存地址试试!两次地址是不连续的,中间多余的几个字节的地址大小是有一部分来存放free的时候停止的标志位的,
这个在VS DEBUG上,到是见过,我用的VS2013,每个new的内存前面后面都用会用4个0xfd进行分隔,但好像只在DEBUG下才这样,主要是为了对内存的使用情况进行跟踪,但这种停止位不好设置值,因为可能会和用户数据冲突,这个如何解决呢?
NBTestNC 2013-11-16
  • 打赏
  • 举报
回复
引用 6 楼 unituniverse2 的回复:
严重的依赖于实现的东西。 何况也没有指明什么平台上的什么编译器 有可能根本不标记长度的。就比如简单的信任程序员的代码,删除的时候把已占用的标志改成未占用。因为某些场合长度都是已知的(比如某些涉及到内存池放置固定大小对象的算法)。也可能把长度专门集中起来标记到一个特殊区域里,那个区域还记录了各起始地址。反正根本不和分配的那个地址相邻 现在很多地方出题出的说是C++的但是严重的偏向于自己业务方面(不是说这样做是错误的),比如360这样出题还是基于自己主要是做分析的,研究对象都是别人用已知的编译器编译出来的已知的程序,他自己当然很少考虑什么兼容性可移植性一类的东西。对他们来说未来的东西可能会是什么样等出来了的时候再去研究。
恩,具体的实现确实很依赖细节,但360没有提供明确答案,估计考察的是你对细节的了解,以及你如何提出一个合理的解决办法
我看你有戏 2013-11-16
  • 打赏
  • 举报
回复
这个是操作系统记录的啊,new delete可以看作是程序和操作系统的交互 指针如何知道是指针,指针所指的内存块的大小,这都记录在操作系统里面吧,我是这么想的不知道对不对 指针占4个字节,就是记录了地址,所指的内存块大小,肯定是有个地方会记录的,猜测是map
NBTestNC 2013-11-16
  • 打赏
  • 举报
回复
引用 5 楼 todd_leftcode 的回复:
一般的做法是在分配的内存前边加一个长度值,但这个是compiler specific的,也不排除有编译器会使用查表法或其它更高明的办法。而且 new 和 delete 运算符可以重载,理论上你想怎么记都可以。 如果是采用前边存长度的做法,那么长度是记录在返回的指针前边的,也就是 reinterpret_cast<size_t*>(p) - 1的位置(当然不一定是size_t类型的)。也就是说你假如你申请4字节的内存,那系统很可能是分配了8字节,然后4字节记录长度,另4字节给你用。你delete时,系统会根据你提供的指针p进行 *(reinterpret_cast<size_t*>(p) - 1)来取得长度值。
这个方法好,可以解决指针访问问题,又可以记录开辟空间的大小
NBTestNC 2013-11-16
  • 打赏
  • 举报
回复
引用 4 楼 Vegertar 的回复:
分配时会簿记,删除时先查询是否存在。 具体请看 http://www.opensource.apple.com/source/Libc/Libc-594.1.4/gen/malloc.c find_registered_zone 函数实现查找过程
从这个里面看确实是记录了
max_min_ 2013-11-16
  • 打赏
  • 举报
回复
楼主可以试试 malloc两块内存地址试试!两次地址是不连续的,中间多余的几个字节的地址大小是有一部分来存放free的时候停止的标志位的,
max_min_ 2013-11-16
  • 打赏
  • 举报
回复
引用 7 楼 mujiok2003 的回复:
一般会有cookie记住其長度,建议自己调试一下
其实是有标志位记录free停止的.
mujiok2003 2013-11-16
  • 打赏
  • 举报
回复
一般会有cookie记住其長度,建议自己调试一下
line_us 2013-11-16
  • 打赏
  • 举报
回复
看看如何计算和释放内存。
gengchenhui 2013-11-16
  • 打赏
  • 举报
回复
流氓?助纣为虐???
unituniverse2 2013-11-16
  • 打赏
  • 举报
回复
严重的依赖于实现的东西。 何况也没有指明什么平台上的什么编译器 有可能根本不标记长度的。就比如简单的信任程序员的代码,删除的时候把已占用的标志改成未占用。因为某些场合长度都是已知的(比如某些涉及到内存池放置固定大小对象的算法)。也可能把长度专门集中起来标记到一个特殊区域里,那个区域还记录了各起始地址。反正根本不和分配的那个地址相邻 现在很多地方出题出的说是C++的但是严重的偏向于自己业务方面(不是说这样做是错误的),比如360这样出题还是基于自己主要是做分析的,研究对象都是别人用已知的编译器编译出来的已知的程序,他自己当然很少考虑什么兼容性可移植性一类的东西。对他们来说未来的东西可能会是什么样等出来了的时候再去研究。
加载更多回复(8)

64,682

社区成员

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

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