C中的重新分配空间函数.

Andy84920 2003-09-29 06:45:51
#define SIZE 100
int array* = (int *) malloc (SIZE * sizeof(int));
//向array数组赋SIZE个值.
........
现在要扩展数组大小.想搞成两倍的SIZE.
用: array * = (int *)relloc( array*, SIZE*2*sizeof(int));
//不太记得这个函数原形了.好像是这样的吧?

我的问题是:
relloc是先申请两倍SIZE大小的空间,然后让array指向这个空间,再把原来array指向空间的数据"复制"到这个重新分配的空间中来,最后释放掉那个最开始malloc来的空间的吗?因为不可能在原来的地址的最后再申请空间是吧.要全部重新分配才可以呀.那值是如何搞过来的呢?
如果是这样,我觉得这个效率不是很低吗?毕竟复制这么多数据要的时间很多.
...全文
229 16 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
WYC2300 2003-10-08
  • 打赏
  • 举报
回复
哪位大峡能够有更深的体会那四个的用处

来个邮件哦

wyc236657_cn.student@sina.com
hubs 2003-10-08
  • 打赏
  • 举报
回复
天光早的说的且不论是对是错,但觉得他能从其他方面来考虑,就是一篇好文章,你们认为呢???
rogear 2003-10-08
  • 打赏
  • 举报
回复
没用过realloc(),我连malloc都用得很少,一般只是模块初始化的时候一次性用malloc申请好,避免中间不停的调用malloc
Andy84920 2003-10-07
  • 打赏
  • 举报
回复
几天没时间上网.今天逛了一晚CSDN.

翻开这个帖子让我想起了以前看到有人说C++的new delete和C的malloc free
的关系.它们如何比?比什么?有没有可比性?为什么?

希望真正能说的来说几句!我想这才是我们想看到的帖子,而不是什么UP,MARK之类的!
FishCrazy 2003-10-02
  • 打赏
  • 举报
回复
短歌说得对,两种情况都是可能的

我做过测试,realloc以后,得到的地址绝大多数是和之前一样的
TianGuangZao 2003-10-02
  • 打赏
  • 举报
回复
呵呵,主题写着讨论的是 C。
不过我也很想听听 C++ 中 new 和 delete 的具体细节。
plusir 2003-10-02
  • 打赏
  • 举报
回复
佩服楼主,好久没看到这样的帖子了,最近总是看些让人代写作业或者一编译不过就帖大段代码让人调试的帖子,无聊。楼主的问题我不会,学到了不少东西,惭愧的是从来没有想过深入的了解一下。不过我觉得动态内存分配用new和delete会不会更好,那位牛人说一下
短歌如风 2003-10-02
  • 打赏
  • 举报
回复

new和delete是为了C++对象类型的动态分配引入的,它们的特点在于自动调用构造函数和析构函数,并且new在内存分配失败时会抛出异常,因此不用对返回值进行检查。

  由于它们考虑到对象类型,并且考虑到对象的状态有可能依赖this指针,所以没有提供相应的realloc版本(认为用memcpy复制对象数组是个错误),所以在使用PODS类型并且需要realloc能力时还是不要使用new和delete了。(我认为C++的这个考虑并不太好,应该提供realloc的new操作,由程序员决定是否使用,这才符合C++“选择的自由”的精神。)而STL中的vector著名的resize低效也正是的原因,所以我在使用PODS时总是选择basic_string作为顺序存储容器。
TianGuangZao 2003-10-02
  • 打赏
  • 举报
回复
To Andy84920(你也不懂):
可以去看看有关动态内存管理的书:
如《数据结构》严薇敏
或《OPERATION SYSTEM CONCEPTS 》第六版,中文名《操作系统概念》影印,很有名气的恐龙书。
里面都专门有一章的篇幅讲操作系统的动态内存管理。
我们在编译时经常讲的堆其实是内存中我们动态分配内存的地方,刚开始是完整的一整块空闲的内存,经常使用后被分割成很多块,有的块是被使用,称为占用块,有的块未被使用,称为占用块,它们交叉出现,使整个内存区呈现这些占有块和空闲块犬牙交错状态。
每个块里头都包含了一个记录结构,记录了该块的使用情况,或称之为内存状态。
我们可以把这些空闲块用链表的形式串联起来,按需分配内存和回收释放了的内存。
当然这只是最简单的方式,还可以采取比较复杂的如常见的 virtual pages。

明白这个原理后,你上面提到的问题就不难理解了。
当使用 realloc 时,先检查相邻的块是否空闲而且足够满足要求。如果有足够空间,那么直接重新分配即可,不必移动到新的空闲块。
当然通过 virtual pages 技术可以做到让数据的不同部分分布在物理空间不相邻的 frames 上,这可能也就是为什么绝大多数情况地址都和以前一样的原因吧。
当然这主要依赖操作系统,是 malloc 的实现者所要关心的事,不必我们劳神的。

实际的 malloc 实现当然要复杂的多,如果对这方面有兴趣,可以看下面我推荐的文章:
Memory Management talk by Rik van Riel

http://www.kernelnewbies.org/documents/irclogs/mm.log
Too little, too slow
An introduction to memory management and Linux memory management today and tomorrow
http://www.surriel.com/lectures/mmtour.html
两篇连起来看。
这个是 linux 下 malloc 的实现者写的。

如果你觉得效率上的问题,至少你得先看懂别人写的代码,才能下结论是好是坏。
Andy84920 2003-10-01
  • 打赏
  • 举报
回复
还有没有人有高见??>?
Andy84920 2003-09-30
  • 打赏
  • 举报
回复
TO: plainsong(短歌)

"如果你在调用前只把这段内存的地址保存在array中,上面的调用会在realloc失败时导致你无法再找到这段内存地址,也就无法释放它。"

realloc失败时它返回NULL,但为什么会导致无法再找到这段内存地址呢?
它应该是重新分配成功才会让array改变指向的,如果没有重分配成功它还是指向原来的内存区.这样才是它内部要处理好的.为什么在失败时让它无法找到这段内存并释放 呢?搞不懂.
Andy84920 2003-09-30
  • 打赏
  • 举报
回复
TO: playboyxp(learning)

可能是

"将p所指向的已经分配内存的大小改为size,size可以比原来分配的空间大或小"这样吗?

我认为这里的P是用来为了复制数据才有用的.在它后面再加内存,这不太可能,因为这里的内存可能已被占用,要重新分配内存必需全部重新分配.

楼上的和我好像一个意思.

那前面几位同志的意思是,如果不移动它就直接在其后面加找内存.而如果移动的话它就会复制数据然后释放掉原来那块地方的内存咯???

这里还是要谈到复制的问题.效率的问题.
cxjddd 2003-09-29
  • 打赏
  • 举报
回复
不记得原型了?打开头文件看看就得了。

我觉得 realloc () 分配的不可能和原来 malloc () 是一个地址。

用 realloc () 一定会有复制的过程。
playboyxp 2003-09-29
  • 打赏
  • 举报
回复
用realloc()函数
原型void *realloc(void *p,unsigned size)
将p所指向的已经分配内存的大小改为size,size可以比原来分配的空间大或小
短歌如风 2003-09-29
  • 打赏
  • 举报
回复
realloc“可能”会发生内存移动,这时返回值就是新的地址,也可能不移动,这时返回值和传入值相等。关键就是如果不移动的话能不能完成“重分配”。

array = (int *)realloc(array, NewSize)这种写法很危险,因为realloc除了“移动内存”、“不移动内存”外还有一种情况就是“重分配失败”,这时它返回NULL,而原来的内存并不会被释放。如果你在调用前只把这段内存的地址保存在array中,上面的调用会在realloc失败时导致你无法再找到这段内存地址,也就无法释放它。一般下面的调用方法已经成了常识:
{//放到复合语句中以便定义变量
int * Temp = (int *) realloc(array, NewSize);
if (Temp == NULL)
{
//错误处理
}
else
array = Temp;
}
TianGuangZao 2003-09-29
  • 打赏
  • 举报
回复
写错了。

正确应该是:
int * array = (int *)malloc(SIZE * sizeof(int))

int * array = malloc(SIZE * sizeof *array)

下一条感觉更好。

我记忆中 relloc 好像不是你说的那样分配的。
如果原来的地方还有足够的空闲空间可供分配,那么就不用再另外找其它空闲空间。
1. C 语言的指针和内存泄漏 5 2. C语言难点分析整理 10 3. C语言难点 18 4. C/C++实现冒泡排序算法 32 5. C++指针和引用的区别 35 6. const char*, char const*, char*const的区别 36 7. C可变参数函数实现 38 8. C程序内存组成部分 41 9. C编程拾粹 42 10. C语言实现数组的动态增长 44 11. C语言的位运算 46 12. 浮点数的存储格式: 50 13. 位域 58 14. C语言函数二维数组传递方法 64 15. C语言复杂表达式的执行步骤 66 16. C语言字符串函数大全 68 17. C语言宏定义技巧 89 18. C语言实现动态数组 100 19. C语言笔试-运算符和表达式 104 20. C语言编程准则之稳定篇 107 21. C语言编程常见问题分析 108 22. C语言编程易犯毛病集合 112 23. C语言缺陷与陷阱(笔记) 119 24. C语言防止缓冲区溢出方法 126 25. C语言高效编程秘籍 128 26. C运算符优先级口诀 133 27. do/while(0)的妙用 134 28. exit()和return()的区别 140 29. exit子程序终止函数与return的差别 141 30. extern与static存储空间矛盾 145 31. PC-Lint与C\C++代码质量 147 32. spirntf函数使用大全 158 33. 二叉树的数据结构 167 34. 位运算应用口诀和实例 170 35. 内存对齐与ANSI Cstruct内存布局 173 36. 冒泡和选择排序实现 180 37. 函数指针数组与返回数组指针的函数 186 38. 右左法则- 复杂指针解析 189 39. 回车和换行的区别 192 40. 堆和堆栈的区别 194 41. 堆和堆栈的区别 198 42. 如何写出专业的C头文件 202 43. 打造最快的Hash表 207 44. 指针与数组学习笔记 222 45. 数组不是指针 224 46. 标准C字符串分割的方法 228 47. 汉诺塔源码 231 48. 洗牌算法 234 49. 深入理解C语言指针的奥秘 236 50. 游戏外挂的编写原理 254 51. 程序实例分析-为什么会陷入死循环 258 52. 空指针究竟指向了内存的哪个地方 260 53. 算术表达式的计算 265 54. 结构体对齐的具体含义 269 55. 连连看AI算法 274 56. 连连看寻路算法的思路 283 57. 重新认识:指向函数的指针 288 58. 链表的源码 291 59. 高质量的子程序 295 60. 高级C语言程序员测试必过的十六道最佳题目+答案详解 297 61. C语言常见错误 320 62. 超强的指针学习笔记 325 63. 程序员之路──关于代码风格 343 64. 指针、结构体、联合体的安全规范 346 65. C指针讲解 352 66. 关于指向指针的指针 368 67. C/C++ 误区一:void main() 373 68. C/C++ 误区二:fflush(stdin) 376 69. C/C++ 误区三:强制转换 malloc() 的返回值 380 70. C/C++ 误区四:char c = getchar(); 381 71. C/C++ 误区五:检查 new 的返回值 383 72. C 是 C++ 的子集吗? 384 73. C和C++的区别是什么? 387 74. 无条件循环 388 75. 产生随机数的方法 389 76. 顺序表及其操作 390 77. 单链表的实现及其操作 391 78. 双向链表 395 79. 程序员数据结构笔记 399 80. Hashtable和HashMap的区别 408 81. hash 表学习笔记 410 82. C程序设计常用算法源代码 412 83. C语言有头结点链表的经典实现 419 84. C语言惠通面试题 428 85. C语言常用宏定义 450

70,024

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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