11.5扩充内容

//释放内存后仍然继续使用
//释放了内存仍然使用它,将会导致产生野指针

#include<stdio.h>
char *GetStr(void)
{
    char a[80];//定义一个动态存储类型的数组,在栈上进行,由程序自动分配和回收,只在该作用域内有效。
    scanf("%s",a);
    return a;//试图返回局部变量的地址
}
int main()
{
    char *p=NULL;
    p=GetStr();
    puts(p);//试图使用野指针
    return 0;
}

//释放了内存的结果就是改变了内存中的存储数据,使内存存储的内容变成了垃圾。指向它的指针并不会自动变成空指针

//上述例子改正后:
#include<stdio.h>
void GetStr(char *p)//指针形参接收实参传过来的数组首地址
{
    scanf("%s",p);
}
int main()
{
    char a[80];
    char *p=a;
    GetStr(p);
    puts(p);
    return 0;
}
//试图使用空指针,和使用没有初始化指针效果一样
#include<stdio.h>
void GetStr(char *p)
{
    scanf("%s",p);//试图使用空指针
}
int main()
{
    char *p=NULL;
    GetStr(p);
    puts(p);
    return 0;
}
//改为动态内存分配,动态分配的内存不会再函数调用结束后自动释放,必须使用free()才能释放
#include<stdio.h>
#include<stdlib.h>
char *GetStr(void)
{
    char *q=NULL;
    q=(char *)malloc(80);//在堆上分配内存空间,不会产生野指针
    scanf("%s",q);
    return q;//返回堆上内存空间的首地址
}
int main()
{
    char *p=NULL;
    p=GetStr();
    puts(p);
    free(p);
    return 0;
}

总结:
1、不要把局部变量的地址(栈上)作为函数的返回值返回
2、在定义指针变量的同时同时对它进行初始化,要么设置为NULL,要么让它指向合法内存
3、尽量把malloc集中在函数的入口处,free集中在函数的出口处

//缓冲区溢出攻击
#include<stdio.h>
int main()
{
    char str[20];
    gets(str);//有缓冲区溢出的隐患,导致数组越界访问
    puts(str);
    return 0;
}

//为防止缓冲区溢出,使用能够限制输入字符串长度的函数
//fgets(str,N*sizeof(char),stdin);

发布了34 篇原创文章 · 获赞 2 · 访问量 458

猜你喜欢

转载自blog.csdn.net/qq_42148307/article/details/105087589