[C / C++] 关于指针置空和野指针问题的思考.

前言

最近在复习数据结构,在复习到树和二叉树时,被指针置空和野指针问题给搞晕了。

看这一段前序创建二叉树的代码

void PreCreate(BiNode * b){
    ElementType e;
    printf("请输入结点的id(如果输入-1,那么就不在这个枝干上创建结点):\n");
    scanf("%d",&e.id);
    if(e.id == -1){     //如果用户输入了-1,那么将该结点的状态设为-999999,等函数返回之后释放该节点

        /*
            为什么这里不直接释放结点并置空呢
            比如这里写free(b);
                      b = NULL;
            这样做的确可以free掉b。但是却无法执行第二句,也就是将b指针指向NULL
            后果是b成为一个野指针
            野指针的错误非常危险。导致后面无法使用if(b == NULL)这个条件判断
            也就是说后面的程序将无法判断b是否为空指针

            原因待考证,我猜测应该是因为b在该函数中是一个形参。将形参这个空指针指向null恐怕不行
            但是可以free掉这个形参。

            最后要指出的是:
                1.野指针非常危险,如果free掉某个空间之后,不把该空间置空(赋值为NULL)
                  那么后面的程序就无法通过if语句判断该空间是否被释放。
                2.解决该问题的方法是,free掉某空间之后(C++为delete某个空间),立刻将该空间指向NULL
                  以避免野指针带来的极大麻烦。
                3.如果遇到这里的情况,某空间是一个形参。那么就不能通过指向NULL来将该形参对应的背后的
                  实参指针置空。但是却可以通过free(C++为delete),将形参对应背后的实参内存释放。
                4.解决问题3的方法是 将形参改成 指向指针的指针。这样做就太过于麻烦了。
                5.重要的事情说3遍 有malloc就有free,有free就有NULL!
                                  有malloc就有free,有free就有NULL!
                                  有malloc就有free,有free就有NULL!
        */
        b->status = -999999;
        return;
    }


    printf("请输入结点的name:\n");
    scanf("%s",e.name);

    //以下
    b->data = e;    //将输入的结点信息赋值给当前结点的数据域
    b->lchild = (BiNode *)malloc(sizeof(BiNode));   //给左孩子指针分配内存
    PreCreate(b->lchild);                           //递归创建左子树
    if(b->lchild->status == -999999){    //如果创建失败,那么删除刚刚分配的左孩子的内存,并且将指针置空
        free(b->lchild);
        b->lchild = NULL;
    }

    b->rchild = (BiNode *)malloc(sizeof(BiNode));   //给右孩子指针分配内存
    PreCreate(b->rchild);                           //递归创建右子树
    if(b->rchild->status == -999999){    //如果创建失败,那么删除刚刚分配的右孩子的内存,并且将指针置空
        free(b->rchild);
        b->rchild = NULL;
    }
}

要指出的是:

1.野指针非常危险,如果free掉某个空间之后,不把该空间置空(赋值为NULL)

那么后面的程序就无法通过if语句判断该空间是否被释放。

2.解决该问题的方法是,free掉某空间之后(C++为delete某个空间),立刻将该空间指向NULL

以避免野指针带来的极大麻烦。

3.如果遇到这里的情况,某空间是一个形参。那么就不能通过指向NULL来将该形参对应的背后的实参指针置空。但是却可以通过free(C++为delete),将形参对应背后的实参内存释放。

4.解决问题3的方法是 将形参改成 指向指针的指针。这样做就太过于麻烦了。

5.重要的事情说3遍

有malloc就有free,有free就有NULL!
有malloc就有free,有free就有NULL!
有malloc就有free,有free就有NULL!

(续前节)前序遍历二叉树的代码:

void PreOrderTraverse(BiNode *b){
    if(b == NULL)       //这一行对应上面的一大串注释。这里就是通过if语句判断指针是否为NULL
        return;
    printf("%d\t%s\n",b->data.id,b->data.name);
    PreOrderTraverse(b->lchild);
    PreOrderTraverse(b->rchild);
}

最后加上main函数如何调用它们。便于理解:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "DataElement.h"
#include "BinaryLinkedList.h"

void TestBinaryLinkedList();

int main()
{

    TestBinaryLinkedList();
    return 0;
}

void TestBinaryLinkedList(){
    BiNode * node = (BiNode *)malloc(sizeof(BiNode));
    PreCreate(node);
    PreOrderTraverse(node);
    free(node);
    node = NULL;

}

看懂了以上代码和注释,那么关于指针置空和野指针问题,大概就解决了

个人见解。如有错误,欢迎指正

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值