鱼C论坛

 找回密码
 立即注册
查看: 2176|回复: 17

realloc 指针释放

[复制链接]
发表于 2022-4-22 19:49:47 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
realloc处理的指针一般是malloc等返回的,而且如果realloc的长度大于malloc的长度的话,可能会找一块新的连续内存把旧数据拷贝过来,而且释放旧内存

我的问题是:
1、realloc成功之后那么释放旧内存是手动free还是会自动free?
2、需不需要分清况,如果realloc分配成功就释放,如果分配失败返回NULL就不需要释放?

感谢感谢!!!!!!

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-4-22 21:45:02 | 显示全部楼层

1. realloc成功之后原来malloc申请的内存空间还在,如果不需要使用原来指向原来控制的指针,则需要释放
2.不管realloc申请内存是否成功,原来malloc申请的成功的空间肯定是在的。所以还是需要释放原来申请的空间
3.realloc申请更大的内存空间,并把原来malloc申请内存空间的值复制过来
代码如下:
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    char *ptr = (char *)malloc(2 * sizeof (char));
    if (NULL == ptr)
        printf ("内存空间申请失败");
    ptr[0] = 'a';
    ptr[1] = 'b';
    printf ("ptr[0]=%c  ptr[1]=%c\n", ptr[0], ptr[1]);
    char *point = realloc (ptr, 4 * sizeof (char));
    if (NULL == point)
        printf ("内存空间申请失败");
    printf ("point[0]=%c  point[1]=%c  point[2]=%c  point[3]=%c\n", point[0], point[1], point[2], point[3]);  //realloc()申请空间成功,打印内存空间的值

    printf ("ptr[0]=%c  ptr[1]=%c\n", ptr[0], ptr[1]);  //realloc()申请内存空间成功了,但是ptr指向的空间还在
    free (ptr);
    printf ("ptr[0]=%c  ptr[1]=%c\n", ptr[0], ptr[1]);
    return 0;
}
验证如下:
ptr[0]=a  ptr[1]=b
point[0]=a  point[1]=b  point[2]=? point[3]=
ptr[0]=a  ptr[1]=b
ptr[0]=  ptr[1]=

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-4-24 12:45:33 | 显示全部楼层
cjgank 发表于 2022-4-22 21:45
1. realloc成功之后原来malloc申请的内存空间还在,如果不需要使用原来指向原来控制的指针,则需要释放
...

不对吧?
  1. $ cat main.c
  2. #include <stdio.h>
  3. #include <stdlib.h>

  4. int main(void)
  5. {
  6.     char *ptr = (char *)malloc(2 * sizeof (char));
  7.     if (NULL == ptr)
  8.         printf ("内存空间申请失败");
  9.     ptr[0] = 'a';
  10.     ptr[1] = 'b';
  11.     printf ("ptr[0]=%c  ptr[1]=%c\n", ptr[0], ptr[1]);
  12.     char *point = realloc (ptr, 4 * sizeof (char));
  13.     if (NULL == point)
  14.         printf ("内存空间申请失败");
  15.     printf ("point[0]=%c  point[1]=%c  point[2]=%c  point[3]=%c\n", point[0], point[1], point[2], point[3]);  //realloc()申请空间成功,打印内存空间的值

  16.     printf ("ptr[0]=%c  ptr[1]=%c\n", ptr[0], ptr[1]);  //realloc()申请内存空间成功了,但是ptr指向的空间还在
  17.     free (ptr);
  18.     printf ("ptr[0]=%c  ptr[1]=%c\n", ptr[0], ptr[1]);
  19.     return 0;
  20. }
  21. $ gcc-debug -o main main.c
  22. $ ./main
  23. ptr[0]=a  ptr[1]=b
  24. point[0]=a  point[1]=b  point[2]=&#190;  point[3]=&#190;
  25. =================================================================
  26. ==132449==ERROR: AddressSanitizer: heap-use-after-free on address 0x602000000011 at pc 0x561444833646 bp 0x7fffb33ef480 sp 0x7fffb33ef470
  27. READ of size 1 at 0x602000000011 thread T0
  28.     #0 0x561444833645 in main /tmp/main.c:17
  29.     #1 0x7fad402f930f in __libc_start_call_main (/usr/lib/libc.so.6+0x2d30f)
  30.     #2 0x7fad402f93c0 in __libc_start_main@GLIBC_2.2.5 (/usr/lib/libc.so.6+0x2d3c0)
  31.     #3 0x561444833114 in _start (/tmp/main+0x2114)

  32. 0x602000000011 is located 1 bytes inside of 2-byte region [0x602000000010,0x602000000012)
  33. freed by thread T0 here:
  34.     #0 0x7fad40f031b2 in __interceptor_realloc /usr/src/debug/gcc/libsanitizer/asan/asan_malloc_linux.cpp:164
  35.     #1 0x5614448333bb in main /tmp/main.c:12
  36.     #2 0x7fad402f930f in __libc_start_call_main (/usr/lib/libc.so.6+0x2d30f)

  37. previously allocated by thread T0 here:
  38.     #0 0x7fad40f02dd9 in __interceptor_malloc /usr/src/debug/gcc/libsanitizer/asan/asan_malloc_linux.cpp:145
  39.     #1 0x5614448331ff in main /tmp/main.c:6
  40.     #2 0x7fad402f930f in __libc_start_call_main (/usr/lib/libc.so.6+0x2d30f)

  41. SUMMARY: AddressSanitizer: heap-use-after-free /tmp/main.c:17 in main
  42. Shadow bytes around the buggy address:
  43.   0x0c047fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  44.   0x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  45.   0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  46.   0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  47.   0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  48. =>0x0c047fff8000: fa fa[fd]fa fa fa 04 fa fa fa fa fa fa fa fa fa
  49.   0x0c047fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  50.   0x0c047fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  51.   0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  52.   0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  53.   0x0c047fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  54. Shadow byte legend (one shadow byte represents 8 application bytes):
  55.   Addressable:           00
  56.   Partially addressable: 01 02 03 04 05 06 07
  57.   Heap left redzone:       fa
  58.   Freed heap region:       fd
  59.   Stack left redzone:      f1
  60.   Stack mid redzone:       f2
  61.   Stack right redzone:     f3
  62.   Stack after return:      f5
  63.   Stack use after scope:   f8
  64.   Global redzone:          f9
  65.   Global init order:       f6
  66.   Poisoned by user:        f7
  67.   Container overflow:      fc
  68.   Array cookie:            ac
  69.   Intra object redzone:    bb
  70.   ASan internal:           fe
  71.   Left alloca redzone:     ca
  72.   Right alloca redzone:    cb
  73.   Shadow gap:              cc
  74. ==132449==ABORTING
  75. $
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-4-24 16:06:56 | 显示全部楼层
cjgank 发表于 2022-4-22 21:45
1. realloc成功之后原来malloc申请的内存空间还在,如果不需要使用原来指向原来控制的指针,则需要释放
...

realloc不是重新分配内存之后,将原空间拷贝到新空间并自动释放原空间的吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-4-24 17:38:52 | 显示全部楼层
realloc 用过很多次了。无非就是将已经存在的一块内存扩大。

char* p = malloc(1024);
char* q = realloc(p,2048);

现在的问题是我们应该如何处理指针 p。 刚开始按照我最直观的理解,如果就是直接将 p = NULL;。 到最后只需要释放 q的空间就可以了。

因为最近在做个封装。结果在做单元测试的时候发现。有时候我在 free(q); 的时候会出错。这样我就郁闷了。

后来仔细一跟踪,发现 realloc 完以后 q 和 p 的指针地址是一样。不过有时候又不一样。

仔细查了下资料。得到如下信息:

       1.如果 当前连续内存块足够 realloc 的话,只是将p所指向的空间扩大,并返回p的指针地址。 这个时候 q 和 p 指向的地址是一样的。

       2.如果 当前连续内存块不够长度,再找一个足够长的地方,分配一块新的内存,q,并将 p指向的内容 copy到 q,返回 q。并将p所指向的内存空间删除。

这样也就是说 realloc 有时候会产生一个新的内存地址 有的时候不会。所以在分配完成后。我们需要判断下 p 是否等于 q。并做相应的处理。

这里有点要注意的是要避免 p = realloc(p,2048); 这种写法。有可能会造成 realloc 分配失败后,p原先所指向的内存地址丢失。

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-4-24 19:27:33 | 显示全部楼层
jhanker 发表于 2022-4-24 17:38
realloc 用过很多次了。无非就是将已经存在的一块内存扩大。

char* p = malloc(1024);


char* p = malloc(1024);
char* q = realloc(p,2048);
free (p);
p = NULL;
...操作指针q...
free (q);
return 0;

程序不应该有二义性,realloc()后,应该主动释放指针p,操作指针q后,释放q退出。
这种说法应该没有问题吧?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-4-24 19:43:55 | 显示全部楼层
cjgank 发表于 2022-4-24 19:27
char* p = malloc(1024);
char* q = realloc(p,2048);
free (p);

请解释一下这个代码为什么报错

  1. $ cat main.c
  2. #include <stdio.h>
  3. #include <stdlib.h>

  4. int main(void) {
  5.     char *p = malloc(5);
  6.     char *q = realloc(p, 4096);
  7.     free(p);
  8.     free(q);
  9.     return 0;
  10. }
  11. $ gcc-debug -o main main.c
  12. $ ./main
  13. =================================================================
  14. ==133969==ERROR: AddressSanitizer: attempting double-free on 0x602000000010 in thread T0:
  15.     #0 0x7f956125ba79 in __interceptor_free /usr/src/debug/gcc/libsanitizer/asan/asan_malloc_linux.cpp:127
  16.     #1 0x56220aed61af in main /tmp/main.c:7
  17.     #2 0x7f956065230f in __libc_start_call_main (/usr/lib/libc.so.6+0x2d30f)
  18.     #3 0x7f95606523c0 in __libc_start_main@GLIBC_2.2.5 (/usr/lib/libc.so.6+0x2d3c0)
  19.     #4 0x56220aed60a4 in _start (/tmp/main+0x10a4)

  20. 0x602000000010 is located 0 bytes inside of 5-byte region [0x602000000010,0x602000000015)
  21. freed by thread T0 here:
  22.     #0 0x7f956125c1b2 in __interceptor_realloc /usr/src/debug/gcc/libsanitizer/asan/asan_malloc_linux.cpp:164
  23.     #1 0x56220aed619f in main /tmp/main.c:6
  24.     #2 0x7f956065230f in __libc_start_call_main (/usr/lib/libc.so.6+0x2d30f)

  25. previously allocated by thread T0 here:
  26.     #0 0x7f956125bdd9 in __interceptor_malloc /usr/src/debug/gcc/libsanitizer/asan/asan_malloc_linux.cpp:145
  27.     #1 0x56220aed618a in main /tmp/main.c:5
  28.     #2 0x7f956065230f in __libc_start_call_main (/usr/lib/libc.so.6+0x2d30f)

  29. SUMMARY: AddressSanitizer: double-free /usr/src/debug/gcc/libsanitizer/asan/asan_malloc_linux.cpp:127 in __interceptor_free
  30. ==133969==ABORTING
  31. $
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-4-24 19:55:39 | 显示全部楼层
本帖最后由 jhanker 于 2022-4-24 19:57 编辑
人造人 发表于 2022-4-24 19:43
请解释一下这个代码为什么报错


char *q = realloc(p, 4096);
这句执行后,估计原来p指向的空间已经回收
free(p)//屏蔽试试
直接改成 p=q;
然后 free(p);free(q);留一句就行
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-4-24 20:55:05 | 显示全部楼层
jhanker 发表于 2022-4-24 19:55
char *q = realloc(p, 4096);
这句执行后,估计原来p指向的空间已经回收
free(p)//屏蔽试试

嗯,这样就可以了
  1. $ cat main.c
  2. #include <stdio.h>
  3. #include <stdlib.h>

  4. int main(void) {
  5.     char *p = malloc(5);
  6.     char *q = realloc(p, 4096);
  7.     if(q) p = q;
  8.     free(p);
  9.     return 0;
  10. }
  11. $ gcc-debug -o main main.c
  12. $ ./main
  13. $
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-4-24 20:58:51 | 显示全部楼层
jhanker 发表于 2022-4-24 17:38
realloc 用过很多次了。无非就是将已经存在的一块内存扩大。

char* p = malloc(1024);


linux环境下,验证了说法1:q和p指向的内存空间是一样的。
但说法2没有办法验证。
说法1代码如下:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>

  4. int main(void)
  5. {
  6.     char *p = malloc(5);
  7.     if (NULL == p)
  8.     {
  9.         printf ("内存申请失败\n");
  10.         return -1;
  11.     }
  12.     strcpy (p, "hello world");
  13.     printf ("指针p指向内存空间内容:%s\n", p);
  14.     printf ("指针p的值:%p\n", p);
  15.     char *q = realloc(p, 4096);
  16.     if (NULL == q)
  17.     {
  18.         printf ("内存申请失败\n");
  19.         return -2;
  20.     }
  21.     printf ("指针q指向内存空间内容:%s\n", q);
  22.     strcat (q, " welcome to China");
  23.     printf ("操作指针q后,指针q指向的内存空间内容:%s\n", q);
  24.     printf ("realloc()并操作指针q后,指针p指向内存空间内容:%s\n", p);
  25.     printf ("指针q的值:%p\n", q);

  26.     free(q);
  27.     return 0;
  28. }
复制代码


验证结果
  1. 指针p指向内存空间内容:hello world
  2. 指针p的值:0x660010
  3. 指针q指向内存空间内容:hello world
  4. 操作指针q后,指针q指向的内存空间内容:hello world welcome to China
  5. realloc()并操作指针q后,指针p指向内存空间内容:hello world welcome to China
  6. 指针q的值:0x660010
  7. [root@iZbp1fna3figga9ot6y4tvZ test]# vim realloc.c
  8. [root@iZbp1fna3figga9ot6y4tvZ test]# gcc realloc.c && ./a.out
  9. 指针p指向内存空间内容:hello world
  10. 指针p的值:0xfbe010
  11. 指针q指向内存空间内容:hello world
  12. 操作指针q后,指针q指向的内存空间内容:hello world welcome to China
  13. realloc()并操作指针q后,指针p指向内存空间内容:hello world welcome to China
  14. 指针q的值:0xfbe010
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-4-24 21:05:07 | 显示全部楼层
cjgank 发表于 2022-4-24 20:58
linux环境下,验证了说法1:q和p指向的内存空间是一样的。
但说法2没有办法验证。
说法1代码如下:
  1. $ cat main.c
  2. #include <stdio.h>
  3. #include <stdlib.h>

  4. int main(void) {
  5.     {
  6.         char *p = malloc(5);
  7.         char *q = realloc(p, 4096);
  8.         if(p == q) printf("8: p == q\n");
  9.         else printf("9: p != q\n");
  10.         if(q) p = q;
  11.         free(p);
  12.     }
  13.     {
  14.         char *p = malloc(5);
  15.         char *q = realloc(p, 8);
  16.         if(p == q) printf("16: p == q\n");
  17.         else printf("17: p != q\n");
  18.         if(q) p = q;
  19.         free(p);
  20.     }
  21.     return 0;
  22. }
  23. $ gcc-debug -o main main.c
  24. $ ./main
  25. 9: p != q
  26. 17: p != q
  27. $ gcc -g -Wall -o main main.c
  28. $ ./main
  29. 8: p == q
  30. 16: p == q
  31. $



  32. $ cat main.c
  33. #include <stdio.h>
  34. #include <stdlib.h>

  35. int main(void) {
  36.     {
  37.         char *p = malloc(5);
  38.         char *q = realloc(p, 409600);
  39.         if(p == q) printf("8: p == q\n");
  40.         else printf("9: p != q\n");
  41.         if(q) p = q;
  42.         free(p);
  43.     }
  44.     {
  45.         char *p = malloc(5);
  46.         char *q = realloc(p, 8);
  47.         if(p == q) printf("16: p == q\n");
  48.         else printf("17: p != q\n");
  49.         if(q) p = q;
  50.         free(p);
  51.     }
  52.     return 0;
  53. }
  54. $ gcc-debug -o main main.c
  55. $ ./main
  56. 9: p != q
  57. 17: p != q
  58. $ gcc -g -Wall -o main main.c
  59. $ ./main
  60. 9: p != q
  61. 16: p == q
  62. $
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-4-24 21:29:38 | 显示全部楼层


第一段代码,我每次输出结果都一样。
你的输出结果两次结果不一样

  1. #include <stdio.h>
  2. #include <stdlib.h>

  3. int main(void) {
  4.     {
  5.         char *p = malloc(5);
  6.         printf ("p address:%p\n", p);
  7.         char *q = realloc(p, 4096);
  8.         printf ("q address:%p\n", q);
  9.         if(p == q)
  10.             printf("8: p == q\n");
  11.         else
  12.             printf("9: p != q\n");
  13.         if(q) p = q;
  14.         free(p);
  15.     }
  16.     printf ("\n");
  17.     {
  18.         char *p = malloc(5);
  19.         printf ("p address:%p\n", p);
  20.         char *q = realloc(p, 8);
  21.         printf ("q address:%p\n", q);
  22.         if(p == q)
  23.             printf("16: p == q\n");
  24.         else
  25.             printf("17: p != q\n");
  26.         if(q) p = q;
  27.         free(p);
  28.     }
  29.     return 0;
  30. }
复制代码


输出结果:
  1. [root@iZbp1fna3figga9ot6y4tvZ test]# gcc eq.c && ./a.out
  2. p address:0xa61010
  3. q address:0xa61010
  4. 8: p == q

  5. p address:0xa61010
  6. q address:0xa61010
  7. 16: p == q
  8. [root@iZbp1fna3figga9ot6y4tvZ test]# gcc eq.c && ./a.out
  9. p address:0xf0d010
  10. q address:0xf0d010
  11. 8: p == q

  12. p address:0xf0d010
  13. q address:0xf0d010
  14. 16: p == q
  15. [root@iZbp1fna3figga9ot6y4tvZ test]# gcc eq.c && ./a.out
  16. p address:0x24d1010
  17. q address:0x24d1010
  18. 8: p == q

  19. p address:0x24d1010
  20. q address:0x24d1010
  21. 16: p == q
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-4-24 21:31:28 | 显示全部楼层
cjgank 发表于 2022-4-24 21:29
第一段代码,我每次输出结果都一样。
你的输出结果两次结果不一样


嗯,因为编译选项不一样
编译环境也不一样
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-4-24 21:55:09 | 显示全部楼层
人造人 发表于 2022-4-24 21:31
嗯,因为编译选项不一样
编译环境也不一样
      1.如果 当前连续内存块足够 realloc 的话,只是将p所指向的空间扩大,并返回p的指针地址。 这个时候 q 和 p 指向的地址是一样的。

       2.如果 当前连续内存块不够长度,再找一个足够长的地方,分配一块新的内存,q,并将 p指向的内容 copy到 q,返回 q。并将p所指向的内存空间删除。



兄弟,有这两段话的资料出处吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-4-24 22:01:48 | 显示全部楼层
cjgank 发表于 2022-4-24 21:55
兄弟,有这两段话的资料出处吗?

这两句话标准文档中不是这么说的,但是意思一样

http://www.cplusplus.com/reference/cstdlib/realloc/?kw=realloc
  1. The function may move the memory block to a new location (whose address is returned by the function).

  2. The content of the memory block is preserved up to the lesser of the new and old sizes, even if the block is moved to a new location. If the new size is larger, the value of the newly allocated portion is indeterminate.
复制代码


man realloc
  1.        The realloc() function changes the size of the memory block pointed  to
  2.        by ptr to size bytes.  The contents will be unchanged in the range from
  3.        the start of the region up to the minimum of the old and new sizes.  If
  4.        the  new size is larger than the old size, the added memory will not be
  5.        initialized.  If ptr is NULL, then  the  call  is  equivalent  to  mal‐
  6.        loc(size), for all values of size; if size is equal to zero, and ptr is
  7.        not NULL, then the call is equivalent to free(ptr)  (this  behavior  is
  8.        nonportable;  see  NOTES).   Unless  ptr is NULL, it must have been re‐
  9.        turned by an earlier call to malloc(), calloc(), or realloc().  If  the
  10.        area pointed to was moved, a free(ptr) is done.
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-4-24 22:03:39 | 显示全部楼层
cjgank 发表于 2022-4-24 21:55
兄弟,有这两段话的资料出处吗?

man realloc
  1. The realloc() function returns a pointer to the newly allocated memory,
  2.        which is suitably aligned for any built-in type, or NULL if the request
  3.        failed.  The returned pointer may be the same as ptr if the  allocation
  4.        was not moved (e.g., there was room to expand the allocation in-place),
  5.        or different from ptr if the allocation was moved to a new address.  If
  6.        size  was equal to 0, either NULL or a pointer suitable to be passed to
  7.        free() is returned.  If realloc() fails, the original block is left un‐
  8.        touched; it is not freed or moved.
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-4-24 22:31:13 | 显示全部楼层
cjgank 发表于 2022-4-24 21:55
兄弟,有这两段话的资料出处吗?

glibc-2.33 源码

  1.   if ((unsigned long) (oldsize) >= (unsigned long) (nb))
  2.     {
  3.       /* already big enough; split below */
  4.       newp = oldp;
  5.       newsize = oldsize;
  6.     }
复制代码

  1.           newmem = _int_malloc (av, nb - MALLOC_ALIGN_MASK);
  2.           if (newmem == 0)
  3.             return 0; /* propagate failure */

  4.           newp = mem2chunk (newmem);
  5.           newsize = chunksize (newp);

  6.           /*
  7.              Avoid copy if newp is next chunk after oldp.
  8.            */
  9.           if (newp == next)
  10.             {
  11.               newsize += oldsize;
  12.               newp = oldp;
  13.             }
  14.           else
  15.             {
  16.               void *oldmem = chunk2mem (oldp);
  17.               newmem = TAG_NEW_USABLE (newmem);
  18.               memcpy (newmem, oldmem,
  19.                       CHUNK_AVAILABLE_SIZE (oldp) - CHUNK_HDR_SZ);
  20.               (void) TAG_REGION (chunk2rawmem (oldp), oldsize);
  21.               _int_free (av, oldp, 1);
  22.               check_inuse_chunk (av, newp);
  23.               return chunk2mem (newp);
  24.             }
复制代码

  1. void*
  2. _int_realloc(mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize,
  3.              INTERNAL_SIZE_T nb)
  4. {
  5.   mchunkptr        newp;            /* chunk to return */
  6.   INTERNAL_SIZE_T  newsize;         /* its size */
  7.   void*          newmem;          /* corresponding user mem */

  8.   mchunkptr        next;            /* next contiguous chunk after oldp */

  9.   mchunkptr        remainder;       /* extra space at end of newp */
  10.   unsigned long    remainder_size;  /* its size */

  11.   /* oldmem size */
  12.   if (__builtin_expect (chunksize_nomask (oldp) <= CHUNK_HDR_SZ, 0)
  13.       || __builtin_expect (oldsize >= av->system_mem, 0))
  14.     malloc_printerr ("realloc(): invalid old size");

  15.   check_inuse_chunk (av, oldp);

  16.   /* All callers already filter out mmap'ed chunks.  */
  17.   assert (!chunk_is_mmapped (oldp));

  18.   next = chunk_at_offset (oldp, oldsize);
  19.   INTERNAL_SIZE_T nextsize = chunksize (next);
  20.   if (__builtin_expect (chunksize_nomask (next) <= CHUNK_HDR_SZ, 0)
  21.       || __builtin_expect (nextsize >= av->system_mem, 0))
  22.     malloc_printerr ("realloc(): invalid next size");

  23.   if ((unsigned long) (oldsize) >= (unsigned long) (nb))
  24.     {
  25.       /* already big enough; split below */
  26.       newp = oldp;
  27.       newsize = oldsize;
  28.     }

  29.   else
  30.     {
  31.       /* Try to expand forward into top */
  32.       if (next == av->top &&
  33.           (unsigned long) (newsize = oldsize + nextsize) >=
  34.           (unsigned long) (nb + MINSIZE))
  35.         {
  36.           set_head_size (oldp, nb | (av != &main_arena ? NON_MAIN_ARENA : 0));
  37.           av->top = chunk_at_offset (oldp, nb);
  38.           set_head (av->top, (newsize - nb) | PREV_INUSE);
  39.           check_inuse_chunk (av, oldp);
  40.           return TAG_NEW_USABLE (chunk2rawmem (oldp));
  41.         }

  42.       /* Try to expand forward into next chunk;  split off remainder below */
  43.       else if (next != av->top &&
  44.                !inuse (next) &&
  45.                (unsigned long) (newsize = oldsize + nextsize) >=
  46.                (unsigned long) (nb))
  47.         {
  48.           newp = oldp;
  49.           unlink_chunk (av, next);
  50.         }

  51.       /* allocate, copy, free */
  52.       else
  53.         {
  54.           newmem = _int_malloc (av, nb - MALLOC_ALIGN_MASK);
  55.           if (newmem == 0)
  56.             return 0; /* propagate failure */

  57.           newp = mem2chunk (newmem);
  58.           newsize = chunksize (newp);

  59.           /*
  60.              Avoid copy if newp is next chunk after oldp.
  61.            */
  62.           if (newp == next)
  63.             {
  64.               newsize += oldsize;
  65.               newp = oldp;
  66.             }
  67.           else
  68.             {
  69.               void *oldmem = chunk2mem (oldp);
  70.               newmem = TAG_NEW_USABLE (newmem);
  71.               memcpy (newmem, oldmem,
  72.                       CHUNK_AVAILABLE_SIZE (oldp) - CHUNK_HDR_SZ);
  73.               (void) TAG_REGION (chunk2rawmem (oldp), oldsize);
  74.               _int_free (av, oldp, 1);
  75.               check_inuse_chunk (av, newp);
  76.               return chunk2mem (newp);
  77.             }
  78.         }
  79.     }

  80.   /* If possible, free extra space in old or extended chunk */

  81.   assert ((unsigned long) (newsize) >= (unsigned long) (nb));

  82.   remainder_size = newsize - nb;

  83.   if (remainder_size < MINSIZE)   /* not enough extra to split off */
  84.     {
  85.       set_head_size (newp, newsize | (av != &main_arena ? NON_MAIN_ARENA : 0));
  86.       set_inuse_bit_at_offset (newp, newsize);
  87.     }
  88.   else   /* split remainder */
  89.     {
  90.       remainder = chunk_at_offset (newp, nb);
  91.       /* Clear any user-space tags before writing the header.  */
  92.       remainder = TAG_REGION (remainder, remainder_size);
  93.       set_head_size (newp, nb | (av != &main_arena ? NON_MAIN_ARENA : 0));
  94.       set_head (remainder, remainder_size | PREV_INUSE |
  95.                 (av != &main_arena ? NON_MAIN_ARENA : 0));
  96.       /* Mark remainder as inuse so free() won't complain */
  97.       set_inuse_bit_at_offset (remainder, remainder_size);
  98.       _int_free (av, remainder, 1);
  99.     }

  100.   check_inuse_chunk (av, newp);
  101.   return TAG_NEW_USABLE (chunk2rawmem (newp));
  102. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-4-25 09:55:55 | 显示全部楼层
人造人 发表于 2022-4-24 22:01
这两句话标准文档中不是这么说的,但是意思一样

http://www.cplusplus.com/reference/cstdlib/realloc ...

Thanks
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-6 22:30

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表