前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++野指针及c++指针使用注意点

C++野指针及c++指针使用注意点

作者头像
acoolgiser
发布2019-08-31 19:36:03
1.5K0
发布2019-08-31 19:36:03
举报
文章被收录于专栏:acoolgiser_zhuanlan

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/acoolgiser/article/details/100133305

内容转自(部分已被本人编辑):https://www.cnblogs.com/mrlsx/p/5419030.html

野指针及c++指针使用注意点

避免野指针的产生

“野指针”的成因主要有:

1)指针变量没有被初始化。任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。

代码语言:javascript
复制
char *p; //此时p为野指针

2)指针p被free或者delete之后,没有置为NULL,让人误以为p是个合法的指针.

代码语言:javascript
复制
char *p=new char[10];  //指向堆中分配的内存首地址,p存储在栈区
cin>> p;
delete []p; //p重新变为野指针

3)指针操作超越了变量的作用范围。

代码语言:javascript
复制
char *p=new char[10]; //指向堆中分配的内存首地址
cin>> p;
cout<<*(p+10); //可能输出未知数据

指针的注意点:

a.指针指向常量存储区对象

代码语言:javascript
复制
char *p="abc";

此时p指向的是一个字符串常量,不能对*p的内容进行写操作,如srtcpy(p,s)是错误的,因为p的内容为“abc”字符串常量,该数据存储在常量存储区,但可以对指针p进行操作,让其指向其他的内存空间。

b.资源泄漏

问题:

代码语言:javascript
复制
1 #include<iostream>
2 using namespace std;
3 void main()
4 {
5     char *p=new char[3];  //分配三个字符空间,p指向该内存空间
6     p="ab";             //此时改变p的指向,p指向了常量“ab”,而不再是new char分配的内存空间了,new char[3]开辟的三个字符空间没有被释放,从而造成了资源泄漏。
7     delete []p;         //释放时报错,此时p指向的是字符串常量
8 }

结果:卡死

改进:

代码语言:javascript
复制
1 #include<iostream>
2 using namespace std;
3 void main()
4 {
5     char *p=new char[3];  //分配三个字符空间,p指向该内存空间
6     strcpy(p,"ab");      //将"ab"存储到p指向的内存空间,而不是改变p的指向
7     delete []p;         //ok
8 }

结果:正确

c.内存越界

代码语言:javascript
复制
1 char *p=new char[3];  //分配三个字符空间,p指向该内存空间
2 strcpy(p,"abcd");    //将abcd存处在分配的内存空间中,由于strlen("abcd")=4>3,越界
3 delete []p;         //ok

d.返回值是指针

问题:数组p[]中的内容为“hello world”,存储在栈区,函数结束时内容被清除,p变为野指针,可能导致乱码

代码语言:javascript
复制
 1 #include<iostream>
 2 using namespace std;
 3 char *f()
 4 {
 5     char p[]="abc";
 6     return p;
 7 }
 8 void main()
 9 {
10     cout<<f()<<endl;
11 }

结果:

改进:

1.加static限定,延长数组生存期

代码语言:javascript
复制
 1 #include<iostream>
 2 using namespace std;
 3 char *f()
 4 {
 5     static char p[]="abc";  //此时数组为静态数组,存储在全局/静态区,生存期到程序结束,因此函数结束时不会销毁p
 6     return p;
 7 }
 8 void main()
 9 {
10     cout<<f()<<endl;
11 }

结果:

2.定义成指针型数组

代码语言:javascript
复制
 1 #include<iostream>
 2 using namespace std;
 3 char *f()
 4 {
 5     char *p="abc";    //"abc"存储在文字常量区,p是指向常量的指针,生存期到程序结束
 6     return p;
 7 }
 8 void main()
 9 {
10     cout<<f()<<endl;
11 }

结果:

3.动态分配存储空间,存储在堆区

代码语言:javascript
复制
 1 #include<iostream>
 2 using namespace std;
 3 char *f()
 4 {
 5     char *p=new char[5];  //动态分配存储空间,p指向堆区
 6     strcpy(p,"abc");   // 这里不能用p="abc",前面已经说明
 7     return p;
 8 }
 9 void main()
10 {
11     cout<<f()<<endl;
12 }

结果:

e.指针做形参

即所谓的地址传递,我们都知道地址传递的方式,形参的改变会导致实参的改变,但要注意的是,这里的改变是指指针所指内容的改变,而不是指针值的改变。因此,当形参改变会导致实参改变时,指针所指的内容是非const类型的,否则会出错。

1.改变指针内容:

代码语言:javascript
复制
void swap(int *a,int *b)   //交换的是*a,*b,即指针的内容,而不是指针a,b
{
   int t;
   t=*a;
   *a=*b;
   *b=t;
}

2.改变指针值:

代码语言:javascript
复制
#include<iostream>
using namespace std;
void fun(char *p)
{
    p="cba";    //“cba”存放在文字常量区,让p指向常量"abc",这里改变的是指针值,实参并不会改变
}
void main()
{
    char *p="abc";  //“abc”存放在文字常量区,p指向常量"abc"
    fun(p);
    cout<<p<<endl;   //输出"abc",而不是"cba"
}

结果:

如果对于这里不容易理解:笔者作如下解释:

改写代码:(注意看注释)

代码语言:javascript
复制
#include<iostream>
using namespace std;
void fun(char *a)  //给形参换个名字
{
    cout<<a<<endl;   //abc
    a="cba";         //“cba”存放在文字常量区,让a指向常量"cba"
    cout<<a<<endl;   //cba

    //证明这里只改变了指针a的指向,即改变的是指针值a的值,先前是“abc”的地址,后来是“cba”的地址。实参并不会改变。
}
void main()
{
    char *p="abc";  //“abc”存放在文字常量区,p指向常量"abc"
    fun(p);
    cout<<p<<endl;   //输出"abc",而不是"cba"

    p="cba";
	cout<<p<<endl;  //输出“cba”    实参p发生改变
    这就证明:在fun函数中,只是改变了形参的值。
}

main函数和fun函数中的"abc"、"cba"都是存放在文字常量区,是具有各自的编号地址的。可以自己调试用printf("%p\n",p);打印出地址,可以看到两个不同的地址。

继续看下面的情况,修改指针的内容:

代码语言:javascript
复制
#include<iostream>
using namespace std;
void fun(char *p)
{
    p[0]='c';    //改变p的内容,即修改p[0]
}
void main()
{
    char *p="abc";  //p指向常量"abc"
    fun(p);
    cout<<p<<endl;   //error,p所指内容为常量,不能修改
}

结果:

注:p="ab"和strcpy(p,"ab"),含义不一样,前者指针p指向常量“ab”存储区域的首地址,改变了p最开始指向的new申请的内存空间;而后者是将“ab”分配到new申请的内存空间中;

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019年08月29日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 野指针及c++指针使用注意点
  • 指针的注意点:
    • a.指针指向常量存储区对象
      • b.资源泄漏
        • c.内存越界
          • d.返回值是指针
            • e.指针做形参
            相关产品与服务
            对象存储
            对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档