指针在子函数中动态分配空间的问题及解决方法

问题:在对二叉树的基本操作的函数用代码实现的过程中,出现的问题,现将问题代码浓缩以使问题更突出,代码如下:

 

#include<stdio.h>

#include<malloc.h>

voidfun(int *t)

{

    t=(int *)malloc(sizeof(int));

    if(!t) printf("malloc error!\n");   //若分配失败

}

intmain()

{

    int *p;

    printf("before malloc=%d\n",p);

    fun(p);

    printf("after malloc=%d\n",p);

    return 0;

}

 

 

输出结果:

beforemalloc=-858993460

aftermalloc=-858993460

 

从输出结果可以看出,fun函数中的malloc根本就没有分配在p所指向的空间上。

 

反汇编的话我们不能预知malloc分配的空间的地址,所以也就无法从反汇编的角度去解决这个问题.(也可能是个人能力问题。)

 

但是我们可以通过构造不同的代码”陷阱”,从输出结果中看出端倪。

 

#include<stdio.h>

#include<malloc.h>

voidfun(int *t)

{

    t=(int *)malloc(sizeof(int));

    if(!t) printf("mallocerror!\n");   //若分配失败

    printf("in the funmalloc=%x\n",t);

}

intmain()

{

    int *p;

    printf("before malloc=%d\n",p);

    fun(p);

    printf("after malloc=%d\n",p);

    return 0;

}

 

输出结果:

beforemalloc=-858993460

inthe fun malloc=5a0f08

aftermalloc=-858993460

 

到这里,想到以前一个关于子函数值传递的问题:在子函数中改变形参的值不会影响到实参的值。从输出结果看出,malloc确实分配了空间,但是回到主函数还是没有改变。

 

依此再重新构造”陷阱”:(将分配空间的操作改为改变指针指向)

 

陷阱1:

#include<stdio.h>

voidfun(int *t)

{

    printf("in the fun beforechange=%d\n",*t);

    int b=99;

    t=&b;

    printf("int the fun afterchange=%d\n",*t);

}

intmain()

{

    int a=10,*p=&a;

    printf("int the main beforefun=%d\n",*p);

    fun(p);

    printf("in the main afterfun=%d\n",*p);

    return 0;

}

输出结果:

 

intthe main before fun=10

inthe fun before change=10

intthe fun after change=99

inthe main after fun=10

 

 

 

请区别一下代码:

 

陷阱2:

#include<stdio.h>

voidfun(int *t)

{

    printf("in the fun beforechange=%d\n",*t);

    *t=99;

    printf("int the fun afterchange=%d\n",*t);

}

intmain()

{

    int a=10,*p=&a;

    printf("int the main beforefun=%d\n",*p);

    fun(p);

    printf("in the main afterfun=%d\n",*p);

    return 0;

}

 

输出结果:

 

intthe main before fun=10

inthe fun before change=10

intthe fun after change=99

inthe main after fun=99

 

 

分析:

 

在陷阱1中:在主函数的fun(p);中,我们传递给fun子函数的是p中的内容,也即一个指向a的地址,子函数会为这个参数临时分配空间以存储这个参数,而子函数进行的t=&b;操作会将b的地址送入这个原本为参数分配的空间中,跟p指向a没有半毛钱关系,在子函数被调用完成后,这个保存参数的空间就被释放了,不但b没有被指向了,连b所占的空间都释放了。此时p依然指向a。

 

而在陷阱2中:传递给fun子函数的同样是p中的内容,同样是指向a的地址,同样的子函数会为这个参数临时分配空间以存储这个参数,但是*t=99;的操作却是从这个临时分配的空间里面取出内容,也即指向a的地址,再将99赋给这个地址所指向的内容,这样的就是实打实的改变了a的值,但是p依然指向a。

 

由以上分析可以知道最初的问题代码的问题所在了:给子函数传递一个指向要分配空间的指针的参数,这个参数就是指向指针的指针,才能真正的给这个指针分配空间。

 

依此纠正错误,正确的代码如下:

 

#include<stdio.h>

#include<malloc.h>

voidfun(int **q)

{

    printf("_fun_beforemalloc=%d\n",*q);

    *q=(int *)malloc(sizeof(int));

    if(!(*q)) printf("mallocerror!\n");

    printf("_fun_aftermalloc=%d\n",*q);

}

intmain()

{

    int *p;

    printf("_main_before fun=%d\n",p);

    fun(&p);

    printf("_main_after fun=%d\n",p);

    return 0;

}

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值