野指针产生的原因和避免方法

本文深入探讨了C语言中指针初始化的重要性,特别是结构体成员指针的初始化方法及如何正确使用malloc和free函数进行内存管理。详细解释了野指针的概念及其形成原因,并提供了防止野指针的有效策略。
struct student
{
    char* name;
    int score;
}stu, *pstu;

int main(void)
{
    strcpy(stu.name, "Jimy");
    stu.score =99;
    return0;
}

这是很多人都容易犯的错误:定义了结构体变量stu,但结构体内部的char * name在定义结构体时只是为其分配了4字节的内存,没有指向一个合法的地址,这时其指针指向的区域只是一些乱码,有事还没有访问权限。这就是我们通常所说的野指针,它是许多程序bug的根源。

为了避免出现野指针,通常我们需要将指针初始化为NULL,用完后也为其赋值为NULL

结构体成员指针往往会被我们忽视,注意它也需要初始化,且需要为结构体指针分配足够的内存,真是就用到了malloc这个宏,使用方法如下:

给指针变量赋初值:

方法一:char * p = (char * )malloc(sizeof(char));

方法二:char * p = NULL;

给数组赋初值:

方法一: int a[10] = {0};

方法二: memset(a, 0, sizeof(a));

memset函数有3个参数:第一个是要被设置的内存起始地址;第二个是要被设置的值;第三个是要被设置的内存大小,单位为字节;

给结构体指针赋初值:

方法一: pstu = (struct student *)malloc(sizeof(struct student));

常见错误: pstu = (struct student *)malloc(sizeof(struct student *));

 

为了避免出现野指针,在程序的debug版本里可以如下处理:

在函数的入口处使用assert(NULL != p)对参数进行校验。或者用if(NULL != p)来校验。它会提醒我们有没有初始化指针,起到定位错误的功能。

assert是个宏,它后面括号里的条件若不满足,则程序终止运行并提示出错。

 

使用完指针后务必记得释放指针所指向的内存,否则不知道什么时候我们又改变了指针的值,使其变成了野指针!

这里就需要free(p)这个函数的帮忙了,它可以切断指针与指向内存的联系。但是需要注意的是free对于同一指针变量只能使用一次。不然会导致出错或者内存泄漏。

释放完内存后另指针的值变为NULL!

如下:

free(p);

p = NULL;

同理:

void main22()

{

        char *p = NULL;

        p = (char *)malloc(100); //char p[100];

        strcpy(p, "abcdefg");

        if (p != NULL)

        {

                  free(p);     //指针所指向的内存空间已经改变、但是指向没有改变 

        }

        if (p != NULL)//指针变量还是指向原来的内存空间,但是内存空间已经被释放

        {

                  free(p);//因此这里再次释放程序就会bug

        }

        system("pause");

产生野指针原因的本质:指针变量和它所指内存空间变量是两个不同的概念。

解决方法:

1、定义指针时,把指针变量赋值成NULL

2、释放内存是,先判断指针变量是否为NULL

3、释放完内存后,把指针变量重新复制成NULL

### 指针的定义 指针(Wild Pointer)是一个指针变量,它指向一个已经被释放的内存地址,或者是一个未知的内存地址。指针的存在是编程中的一个严重问题,因为它可能导致程序崩溃、数据损坏或其他不可预期的行为[^1]。 ### 指针产生原因 1. **指针定义时未被初始化**指针在被定义的时候,如果程序不对其进行初始化,它会随机指向一个区域,因为任意指针变量(除了 `static` 修饰的指针)的默认值都是随机的[^2]。 2. **指针被释放时没有置空**:在用 `malloc()` 开辟空间时,若开辟成功,指针指向开辟的内存空间的首地址。当使用 `free()` `delete` 释放该内存空间后,如果程序员没有对指针进行置空或者其他赋值操作,就会使其成为指针[^2]。 3. **指针操作超越变量作用域**:不要返回指向栈内存的指针或者引用,因为栈内存在函数结束的时候会被释放,此时指针指向的内容已经无效,该指针就会变成指针[^2]。 4. **指向的内存被释放但指针未处理**:如果一个指针指向的内存已经被释放,但指针本身仍然保持指向已释放的内存,这也会导致指针的问题[^3]。 ### 指针避免方法 1. **初始化指针**:在定义指针时,就对其进行初始化。如果暂时不知道该指针指向何处,可以将其初始化为 `NULL`(在 C++ 中推荐使用 `nullptr`)。示例代码如下: ```c #include <stdio.h> #include <stdlib.h> int main() { int *ptr = NULL; // 初始化指针为 NULL ptr = (int *)malloc(sizeof(int)); if (ptr != NULL) { *ptr = 10; printf("%d\n", *ptr); free(ptr); ptr = NULL; // 释放内存后将指针置为 NULL } return 0; } ``` 2. **释放内存后及时置空指针**:当使用 `free()` 或 `delete` 释放指针所指向的内存后,要立即将指针置为 `NULL` 或 `nullptr`,避免再次使用该指针时出现问题。 3. **避免返回指向栈内存的指针**:尽量不要在函数中返回指向栈内存的指针或引用,因为函数结束后栈内存会被释放。如果需要返回动态分配的内存,可以使用 `malloc()` 或 `new` 来分配堆内存。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值