【Linux C】浅谈指针(二)——野指针

本文详细解析了野指针的定义、成因及其对内存泄漏的影响,通过实例讲解了如何避免野指针并安全使用指针。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写在前面的话:
1. 版权声明:本文为博主原创文章,转载请注明出处!
2. 博主是一个小菜鸟,并且非常玻璃心!如果文中有什么问题,请友好地指出来,博主查证后会进行更正,啾咪~~
3. 每篇文章都是博主现阶段的理解,如果理解的更深入的话,博主会不定时更新文章。
4. 本文最后更新时间:2020.7.8

正文开始

关于野指针和内存泄漏

野指针:随机指向一块内存的指针。即没有人为的初始化,而是由系统默认初始化。

野指针的影响:会导致内存泄漏。

例如:

#include <stdio.h>

int main()
{
    char *ptr;

    printf("Please input ptr = ");
    scanf("%s", ptr);

    printf("ptr = %s\n", *ptr);

    return 0;
}
运行结果:
Please input ptr = cong
段错误

指针ptr没有申请空间,但直接使用了,对应的空间不一定能用。即:定义了一个指针变量,是一个局部变量,但没有初始化,由系统随机初始化。这时给ptr指向的空间赋值,但不一定是系统随机给的地址。

总结一下:

野指针的成因

1. 指针变量没有被初始化

2. 指针p被free或delete后,没有置为NULL,让人误以为p是个合法的指针

3. 指针操作超越了变量的作用范围

造成内存泄漏的原因

1. 指向(访问)了一块没有访问权限的内存(如果正确使用了指针,系统会给指针分配相应的空间,但如果指针指向的内存不是系统分配的,那么会被判定为没有权限)

2. 指向(访问)了一块已经释放的内存

如何避免野指针

避免野指针,最为重要的一点就是要养成良好的编码习惯。

1. 当定义一个指针,且该指针没有指向时,将其置为空。

这里便引入了空指针的概念。

什么是空指针?

If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.( 如果一个空指针常量赋给了一个有类型的指针变量,那么这个指针就叫空指针。它不指向任何的对象或者函数)

也就是说空指针不指向任何对象,空指针的值是NULL。那么NULL又是什么呢?NULL是在“stddef.h”中定义的一个宏,它的值和任何有效指针的值都不同。即:

#define NULL (void *)0    // 代表0地址

0地址的特点:不允许访问,也不允许操作。

如下所示:

#include <stdio.h>

int main()
{
    char *ptr = NULL;

    printf("Please input ptr = ");

    scanf("%s", ptr);

    printf("ptr = %s\n", ptr);

    return 0;
}

运行结果:

Please input ptr = hello
ptr = (null)

也就是说当一个指针指向空时,就不能对指针赋值或访问。

 

那么为什么要将没有指向的指针赋值为空呢?请看以下例子:

#include <stdio.h>

int main()
{
    char *ptr = NULL;

    printf("Please input ptr = ");

    scanf("%s", ptr);

    while (*ptr != NULL)
    {
        ptr++;
    }

    return 0;
}

运行结果:

Please input ptr = hello
段错误

从以上例子可以看出,以后如果出现段错误,我们可以找代码中有没有访问指向空的指针。

将没有指向的指针置为空的好处

1. 不能操作,也不能访问0地址

2. 会出现段错误,好查找调试

2. 当要往指针指向的空间赋值时,先看是否给它分配了合法的空间。

可以使用malloc分配空间。

malloc向系统申请分配指定size个字节的内存空间。返回类型是 void* 类型。void* 表示未确定类型的指针。C/C++规定,void* 类型可以强制转换为任何其它类型的指针。

malloc返回值的类型是void *,所以在调用malloc 时要适时地进行类型转换,将void* 转换成所需要的指针类型。

具体代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_SIZE sizeof(char) * 100

int main()
{
    char *ptr = (char *)malloc(MAX_SIZE);  //分配内存

    if (NULL == ptr)  //检查是否分配成功
    {
        printf("malloc error!\n");
        exit(1);
    }

    memset(ptr, 0, MAX_SIZE);  //清空分配好的空间中的数据

    printf("Please input ptr = ");

    scanf("%s", ptr);

    printf("ptr = %s\n", ptr);

    free(ptr);  //释放

    ptr = NULL;  //指针置空

    return 0;
}

运行结果:

Please input ptr = hello
ptr = hello
 

总结一下流程
1. 分配内存空间。
2. 检查分配是否成功。若分配成功,则返回内存的首地址;若分配失败,则返回NULL,并退出程序。
3. 清空分配好的空间的数据,即原来的内存中的数据。(使用malloc或bzero函数)
4. 使用内存。
5. 使用完内存之后,需要释放内存。
6. 对指针置空。若释放内存之后不将指针置空,这时如果继续使用该指针,指针会成为野指针。

在C语言中,指针之间赋值必须是相同指针类型赋值。例如:

以下为相同指针类型赋值:

#include <stdio.h>

int main()
{
    int num = 0x12345678;

    int *p = &num;

    printf("num = %x\n", *p);

    return 0;
}

运行结果:

num = 12345678

以下为不同指针类型赋值:

#include <stdio.h>

int main()
{
    char ptr[100];

    int num = 0x12345678;

    int *p = &num;

    ptr = p;

    printf("num = %x\n", ptr);

    return 0;
}

编译时报错:

malloc.c: 在函数 ‘main’ 中:
malloc.c:11: 错误:赋值时类型不兼容

从不兼容指针类型赋值可能导致的结果:
1. 取值取不完整
2. 越界


注意:在用malloc分配空间时,可以用宏定义,用宏定义可以提高代码的维护性。

void *可以被看做是一种万能指针,可以接受任何指针类型的值。

它的缺点是:不能对地址指向的空间操作(即不能取值)。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值