野指针和常见的内存错误

1、什么是野指针

指向不可用或者不应该被使用的内存的指针(注意,不是NULL指针)

1) 如果 p 指向一个非法地址(如代码区和已经被释放的栈地址,不可用),那么会造成 段错误(崩溃)
2) 如果 p 指向一个未知变量或者已被释放的堆的内存地址(不应该被使用),那么会造成 预想不到的(值被修改的问题)

2、产生野指针的原因

1、指针变量没有初始化。属于栈区的变量没有初始化,如果没有初始化,值是不确定的。也就是说,没有被初始化的指针,指向的是不应该被使用的内存,如果使用了该内存,会产生不可知的错误。

#include<stdio.h>

int main()
{
    int *p;
    printf("%p\n",p);

    *p = 10;
    printf("%d\n", *p);
    
    return 0;
}

 2、指向堆区的指针被free()后,没有置为NULL。free()函数是把指针所指向的内存区域释放,使得该区域成为自由内存,可以被再次分配。但是,函数并没有把指针本身的内容置空,指针仍然指向已经被释放的堆内存。

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

int main()
{
    int *p = malloc(sizeof(int));
    if(!p){
        printf("malloc error\n");
        exit(1);
    }
    printf("p:%p\n",p);
    *p = 10;
    printf("*p:%d\n", *p);

    free(p);
    printf("p:%p\n",p);//p指针本身的值还是free()之前的值
    printf("*p:%d\n", *p);//该内存在没有被再次被分配重新赋值之前还是原来的值
    
    int *i = malloc(sizeof(int));
    if(!i){
        printf("malloc error\n");
        exit(1);
    }
    printf("i:%p\n",i);//该内存区域被释放,可以被再次分配
    
    *i = 20;
    printf("*i:%d\n", *i);

    *p = 10;
    printf("*i:%d\n", *i);//i指针指向的内存区域被p指针修改了,但这是不应该发生的
    free(i);
    i = NULL;
    P = NULL;
    return 0;
}

 3、指针操作越界。C语言不做越界检查,所以由于程序逻辑上的错误,导致指针访问了不应该访问的内存。常见的是数组越界。

#include<stdio.h>

int main()
{
    int arr[5] = {1,2,3,4,5};

    for(int i = 0; i <= 5; ++i)
    {
        printf("%d\t",arr[i]);
    }
    printf("\n");

}

 4、指针函数返回指向栈内存的指针。函数指针会返回一个指针,然后在主调函数中使用该指针指向的内存。因此,指针函数不能返回在该函数内指向栈内存的指针,因为栈区是由程序自动释放。

#include<stdio.h>

int *add(int a,int b){
    int *sum ;
    *sum= a + b;
    return sum;
}
int main()
{
    int *s = add(1 , 2);
    printf("%d\n",*s);
    return 0;      
}

#include<stdio.h>
#include<stdlib.h>
int *add_v1(int a,int b){
    int *sum = malloc(sizeof(int));
    if(sum == NULL){
        printf("malloc error\n");
        exit(1);
    }
    *sum= a + b;
    return sum;
}

void add_v2(int a,int b, int *sum){
    *sum = a + b ;
}
int main()
{
    int *s1 = NULL;    
    s1 = add_v1(1 , 2);
    printf("%d\n",*s1);
    free(s1);
    s1=NULL;
    //因为s1在add_v1函数内malloc分配了堆内存,所以使用结束也要free,否者会造成内存泄漏。
    //这种函数写法和调用方式很容易造成内存泄漏
    int *s2 = (int *)malloc(sizeof(int));
    if(s2 == NULL){
        printf("malloc error\n");
        exit(1);
    } 
    add_v2(1,2,s2);
    printf("%d\n",*s2);
    free(s2);
    s2 = NULL;
    return 0;      
}

 3、常见的内存错误

1、内存没有分配成功,却使用了它。

解决办法:在使用指针前一定要确保指针是有效的。对于使用malloc申请的指针,使用if(p ==NULL)检验指针有效性。

2、内存虽然分配成功,但是并未初始化就使用它。

3、内存越界

4、忘记释放内存,造成内存泄漏

        1)动态内存申请没有释放

        2)多进程情况下,进程结束没有进行资源回收

        3)网络通信中,创建了socket套接字但没有释放

        4)打开的文件描述符没有释放

内存泄露简单的讲就是申请了一块内存空间,使用完毕后却没有释放掉。一般表现方式是随着程序运行时间越长,占用内存越多,最后虚拟内存空间用尽,程序奔溃。

5、释放了内存却继续使用它。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值