吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1085|回复: 11
收起左侧

[已解决] c语言realloc疑惑

[复制链接]
mxwawaawxm 发表于 2022-4-24 08:01
本帖最后由 mxwawaawxm 于 2022-4-29 19:08 编辑

根据网上一些知识,c语言里,realloc成功扩充内存块,返回的地址不一定是原地址。
比如写的这段测试代码
[C] 纯文本查看 复制代码
#include <stdio.h>
#include <stdlib.h>

int main(int argc, const char *argv[])
{
    int *tmp = (int *)malloc(sizeof(int)*5);
    int idx;

    printf("tmp address : %p\n", tmp);

    for (idx=0; idx<5; idx++) {
        *(tmp+idx) = idx;
        printf("tmp: %d\n", *(tmp+idx));
    }

    tmp = (int *)realloc(tmp, 100000*sizeof(int));

    printf("========================================\n");
    printf("tmp address : %p\n", tmp);
    
    for (idx=0; idx<100000; idx++) {
        *(tmp+idx+5) = idx+5;
    }

    for (idx=0; idx<5; idx++) {
        *(tmp+idx) = idx;
        printf("tmp: %d\n", *(tmp+idx));
    } 

    free(tmp);   

    return 0;
}

中间的tmp = (int *)realloc(tmp, 100000*sizeof(int));
经测试,这里没有返回原地址。

一些资料里,说realloc成功扩充内存块后,会释放例子里的 tmp 指向的内存块
如果当前内存段后面的空闲字节不够,会把 tmp 指向的内存中的数据复制到新地址
所以总看到(int *)realloc(tmp, 100000*sizeof(int));
这一步时,有的资料提示不能像上面这么写tmp = (int *)realloc(tmp, 100000*sizeof(int));
例如要写成int *tmp2 = (int *)realloc(tmp, 100000*sizeof(int));
检测tmp2不为空指针后,然后再写tmp = tmp2


但我的疑问是,在上面的例子中,realloc成功扩充内存块,把 tmp 指向的内存中的数据复制到新地址,并返回新地址
虽然tmp指向的内存块已经被释放,但tmp指针变量还存在,是不是就成为所谓的野指针(不太懂)
那这时,把tmp指针重新指向新地址,不就可以了。
为什么一定得再定义一个指量tmp2
请大大们解疑。

免费评分

参与人数 1吾爱币 +1 收起 理由
zohoChou + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

25535 发表于 2022-4-24 08:39
realloc失败了,原地址不会释放,但是会返回NULL,这是你不用TMP2,那就没无法指向原地址

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
mxwawaawxm + 1 + 1 谢谢@Thanks!

查看全部评分

pzx521521 发表于 2022-4-24 09:21
3L 正解,  举个栗子:  如果内存不够, 就会realloc失败了 返回null, 如果你不用temp2, 原temp地址就丢失了(变为null)

解释下野指针:
指针就是一个内存地址
,野指针的定义是指针指向了一个地址是不确定的变量,此时去解引用就是去访问了一个不确定的地址,所以结果是不可预测的

内存里面是和硬盘一样删除数据并不会全部设置为0.
如果你不知道某一块内存里面存的东西就用, 就会有出现野指针
tmp指向的内存块已经被释放,这块内存有可能被其他地方重新占用, 重新写值, tmp指针变量还存在, tmp就是一个内存地址, 可以认为是一个野指针

免费评分

参与人数 2吾爱币 +1 热心值 +2 收起 理由
zohoChou + 1 谢谢@Thanks!
mxwawaawxm + 1 + 1 谢谢@Thanks!

查看全部评分

quandu 发表于 2022-4-24 10:18
楼上正解较多,推荐查看man手册
man 3 realloc 里面有一句话
“If realloc() fails, the original block is left untouched; it is not freed or moved.”
当然从源码也能看出一些些
[C] 纯文本查看 复制代码
       /* Note the extra SIZE_SZ overhead. */
       if (oldsize - SIZE_SZ >= nb)
         return oldmem;                         /* do nothing */
 
       /* Must alloc, copy, free. */
       newmem = __libc_malloc (bytes);
      if (newmem == 0)
        return 0;              /* propagate failure */

       memcpy (newmem, oldmem, oldsize - CHUNK_HDR_SZ);
       munmap_chunk (oldp);
       return newmem;

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
mxwawaawxm + 1 + 1 谢谢@Thanks!

查看全部评分

A学习的小菜鸟 发表于 2022-4-24 10:31
你直接先用tmp指针用malloc了一段内存,这时候tmp已经指向了一段内存了,但是你下面的代码却在没有将tmp进行释放的前提下,又realloc了新的一段内存,这时候就会出现指针指向错误的,realloc自然也是失败的,建议你在申请内存的时候,最好加上一个判断,如果失败就直接返回null ,这样的话,可以避免野指针出现错误,这类错误很难排查的

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
mxwawaawxm + 1 + 1 谢谢@Thanks!

查看全部评分

 楼主| mxwawaawxm 发表于 2022-4-24 10:52
25535 发表于 2022-4-24 08:39
realloc失败了,原地址不会释放,但是会返回NULL,这是你不用TMP2,那就没无法指向原地址

谢谢。那如果假定realloc是成功的
tmp = (int *)realloc(tmp, 100000*sizeof(int));
这样写,是可以么。

之所为要用新定义的指针变量int *tmp2 = (int *)realloc(tmp, 100000*sizeof(int));
是为了做好判断,判断realloc是否成功
25535 发表于 2022-4-24 11:10
本帖最后由 25535 于 2022-4-24 11:11 编辑
mxwawaawxm 发表于 2022-4-24 10:52
谢谢。那如果假定realloc是成功的
tmp = (int *)realloc(tmp, 100000*sizeof(int));
这样写,是可以么 ...

假定他一定成功是可以这样去写,
但是实际可能会出现失败的,失败后如果没有其他指针指向该地址那么 存储的数据就会丢失,还会造成内存泄漏。
另外关于野指针就是 记得初始化,释放后要指控 不要越界
 楼主| mxwawaawxm 发表于 2022-4-24 13:51
quandu 发表于 2022-4-24 10:18
楼上正解较多,推荐查看man手册
man 3 realloc 里面有一句话
“If realloc() fails, the original block  ...

这源码看不懂
看起来像c
又有这些符号-
quandu 发表于 2022-4-24 20:49
mxwawaawxm 发表于 2022-4-24 13:51
这源码看不懂
看起来像c
又有这些符号-

这是glibc中的源码,读源码的话,不是希望很深入就可以粗略的看一看。
你已经知道了realloc,如果内存块不够,则要重新分配内存。
那么一般会有一个判断够不够,够的话则可以返回原来的值,不够那就需要重新分配,对不对。
你看2,3行是不是感觉在判断够不够,第6行看起来在重新分配,第7行就说分配失败,就返回0,也就是realloc失败返回NULL,第10行是成功的时候,成功了则需要把原来的内容拷贝回来。第11行就类似于释放操作,因为函数名中有un map,意思是取消 映射,即便是不理解,也可以这么猜测,这就是归纳学习

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
mxwawaawxm + 1 + 1 谢谢@Thanks!

查看全部评分

zohoChou 发表于 2022-5-3 14:25
正好在学习指针与内存,看到了各位的解答深受启发,不过有点小疑问,某些教程说不应对上述例子中的tmp做出修改,因为其已被系统回收,包括free()也是不可以的,比如tmp99=realloc(tmp,99*sizeof(int));
free(tmp);
这是错误的,请问这有什么道理吗?
还有,下附我的某个无法运行的奇怪程序(总体思路,动态扩充数组),恳请各位大佬不吝赐教,感谢!
[C] 纯文本查看 复制代码
#include <stdio.h>
#include <stdlib.h>
#define int_space sizeof(int)
int main (void) {
    int num;
    int count =0;
    int *p= (int*)calloc(1,int_space);
    scanf("%d",&num);

    while(num!=0) {
        p[count] = num;
        printf("n=%d,p[%d]=%d\n",sizeof(p)/int_space,count,num);
        int *temp_p=(int *)realloc(p,(count+2)*int_space);
        p=NULL;
        if(temp_p!=NULL) {
            printf("Success\n");
            ++count;
            //free(p);
            p=temp_p;
            temp_p=NULL;
            scanf("%d",&num);
            printf("%llu\n",sizeof(p)/int_space);
        }
        else {

            printf("Error!");
        }
    }
    /*
        for(unsigned long long int i=0;i<=(sizeof(*p)/sizeof(int));i++){
            printf("%d",p[i]);
        }*/


    return 0;

}
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 12:36

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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