野指针的定义和避免

1.我们知道在程序中使用了一个野指针,会引起程序出错,造成段错误。下面我举一个例子指出野指针

#include <stdio.h>

int main()
{
    char *str;

    printf("input a str\n");
    scanf(" %s", str);

    printf("%s\n", str);

    return 0;
}

下面我对*str进行赋值,会出现什么后果呢?

[root@localhost 0720]# ./a.out 
input a str
hello
段错误
我们看到运行结果出现了段错误!那是因为str是野指针。

那什么是野指针呢?野指针就是随机指向一块内存的指针。如果一个指针被定义成了野指针,那对这个指针的使用的危害是多么的大,它可能改变程序中任何地方的值。

那到底是造成野指针的原因有哪些?

a.指针指向一块已经释放的内存。

b.指针指向一块没有访问权限的内存。

下面我们来讲讲怎么来避免野指针:

a.给指针赋值的时候,先检查指针是否分配了合理的内存空间。

b.释放内存的指针要给指针赋值为NULL。(编码规范)

比如:

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

int main()
{
    char *str;

    str = (char *)malloc(sizeof(char) * 100);
    printf("input a str\n");
    scanf(" %s", str);

    printf("%s\n", str);

    return 0;
}
[root@localhost 0720]# ./a.out 
input a str
hello
hello

在堆上分配了空间,就避免了野指针。


### 指针悬空指针定义、区别及处理方法 #### 定义 - **指针**:未初始化或已释放的指针,其指向的内存地址是未知的。尝试解引用指针会导致未定义行为,可能引发程序错误或安全漏洞[^5]。 - **悬空指针**:曾经指向有效内存的指针,但在其所指向的内存被释放后,仍然保持对该内存的引用。此时,该指针变为悬空状态,解引用可能导致程序崩溃或不可预测的行为[^3]。 #### 区别 - **状态**: - 指针从未被正确初始化,或者在使用后未重新初始化,因此其指向的地址是随机的[^5]。 - 悬空指针最初是有效的,但由于内存管理问题(如释放了所指向的内存),现在变得无效[^3]。 - **安全性**: - 指针的风险更高,因为它可能指向任何随机地址,包括有效的内存区域,从而导致难以调试的问题[^4]。 - 悬空指针的风险相对较低,但仍然可能导致程序崩溃或数据损坏[^4]。 #### 处理方法 - **避免指针**: - 在声明指针时立即初始化为 `nullptr` 或指向有效的内存地址。 - 确保在使用指针之前对其进行检查,确认其是否已被正确初始化[^2]。 - **避免悬空指针**: - 在释放动态分配的内存后,立即将相关指针设置为 `nullptr`,以防止意外解引用[^3]。 - 使用智能指针(如 `std::unique_ptr` `std::shared_ptr`)来自动管理内存生命周期,减少手动管理内存带来的错误[^2]。 #### 示例代码 以下代码展示了如何避免指针悬空指针: ```cpp #include <iostream> #include <memory> int main() { // 避免指针 int* p = nullptr; // 初始化为 nullptr int* q = new int(10); // 动态分配内存 if (p == nullptr) { std::cout << "p is a null pointer." << std::endl; } std::cout << "*q = " << *q << std::endl; // 避免悬空指针 delete q; // 释放内存 q = nullptr; // 将指针置为 nullptr // 使用智能指针 std::unique_ptr<int> r = std::make_unique<int>(20); std::cout << "*r = " << *r << std::endl; return 0; } ``` #### 注意事项 - 使用智能指针可以显著减少指针悬空指针的风险,因为它们会自动管理内存的分配释放[^2]。 - 在多线程环境中,确保指针的访问修改是线程安全的,以避免竞争条件导致的指针问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值