第41课 内存操作经典问题分析一

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第41课 内存操作经典问题分析一相关的知识,希望对你有一定的参考价值。

1. 野指针

(1)指针变量中的值是非法的内存地址,进而形成野指针

(2)野指针不是NULL指针,是指向不可用内存地址的指针

(3)NULL指针并无危害,很好判断,也很好调试

(4)C语言中无法判断一个指针所保存的地址是否合法

2. 野指针的由来

(1)局部指针变量没有被初始化

(2)指针所指向的变量在指针之前被销毁

(3)使用己经释放过的指针

(4)进行了错误的指针运算

(5)进行了错误的强制类型转换

【实例分析】野指针初探

#include <stdio.h>
#include <malloc.h>


int main()
{
    int* p1 = (int*)malloc(40); //这里只分配40字节
    int* p2 = (int*)1234567;    //该地址是非法的,进行了错误的强制转换
    int i = 0;
    
    for(i = 0;i < 40; i++)
    {
        *(p1 + i) = 40 - i; //越界访问,p1所指内存总共才40字节,而这里要写入40*4字节
    }

    free(p1);

    for(i = 0; i < 40; i++)
    {
       p1[i] = p2[i]; //p1越界访问,p2非法内存
    }

    return 0;
}

3. 基本原则

(1)绝不返回局部变量局部数组的地址

(2)任何变量在定义后必须用0初始化

(3)字符数组必须确认0结束符后才能成为字符串

(4)任何使用与内存操作相关的函数必须指定长度信息

【实例分析】无处不在的野指针

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

struct Student
{
    char* name;
    int number;
};

char* func()
{
    char p[] = "Hello World!";
    return p; //返回栈中数组,这是很危险的。
}

void del(char* p)
{
    printf("%s\n", p);
    free(p);  //不符谁申请谁释放的原则!
}

int main()
{
    struct Student s; //危险,结构体应先初始化,因为结构体里有指针!
    char* p = func(); //危险,返回局部的数组地址

    //strcpy(s.name, p);//s结构体的name指针是野指针!

    s.number = 99;//合法

    p = (char*)malloc(5);

    strcpy(p, "Hello World!");//越界,源字符串比目标内存大!

    del(p);

    return 0;
}

4. 小结

(1)内存错误是实际产品开发中最常见的问题,然而绝大多数的bug都可以通过遵循基本的编程原则和规范来避免。

(2)在学习的时候要牢记和理解内存操作的基本原则、目的和意义。

以上是关于第41课 内存操作经典问题分析一的主要内容,如果未能解决你的问题,请参考以下文章

第42课 内存操作经典问题分析二

第42课 内存操作经典问题分析2

第12课 经典问题解析一

C之内存操作经典问题解析(三十七)

python 第22课 列表 内存分析 列表常用操作

python 第22课 列表 内存分析 列表常用操作