避免野指针的产生

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

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

char *p; //此时p为野指针

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

char *p=new char[];  //指向堆中分配的内存首地址,p存储在栈区
cin>> p;
delete []p; //p重新变为野指针

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

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

指针的注意点:

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

char *p="abc";

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

b.资源泄漏

问题:

 #include<iostream>
using namespace std;
void main()
{
char *p=new char[]; //分配三个字符空间,p指向该内存空间
p="ab"; //此时p指向常量“ab”,而不再是new char分配的内存空间了,从而造成了资源泄漏
delete []p; //释放时报错
}

结果:卡死

改进:

 #include<iostream>
using namespace std;
void main()
{
char *p=new char[]; //分配三个字符空间,p指向该内存空间
strcpy(p,"ab"); //将"ab"存储到p指向的内存空间
delete []p; //ok
}

结果:正确

c.内存越界

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

d.返回值是指针

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

 #include<iostream>
using namespace std;
char *f()
{
char p[]="abc";
return p;
}
void main()
{
cout<<f()<<endl;
}

结果:

 改进:

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

 #include<iostream>
using namespace std;
char *f()
{
static char p[]="abc"; //此时数组为静态数组,存储在全局/静态区,生存期到程序结束,因此函数结束时不会销毁p
return p;
}
void main()
{
cout<<f()<<endl;
}

结果:

2.定义成指针型数组

 #include<iostream>
using namespace std;
char *f()
{
char *p="abc"; //"abc"存储在文字常量区,p是指向常量的指针,生存期到程序结束
return p;
}
void main()
{
cout<<f()<<endl;
}

结果:

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

 #include<iostream>
using namespace std;
char *f()
{
char *p=new char[]; //动态分配存储空间,p指向堆区
strcpy(p,"abc"); // 这里不能用p="abc",前面已经说明
return p;
}
void main()
{
cout<<f()<<endl;
}

结果:

 e.指针做形参

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

1.改变指针内容:

 void swap(int *a,int *b)   //交换的是*a,*b,即指针的内容,而不是指针a,b
{
int t;
t=*a;
*a=*b;
*b=t;
}

2.改变指针值:

 #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",而不是"bca"
}

结果:

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

 #include<iostream>
using namespace std;
void fun(char *p)
{
p[]='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申请的内存空间中;

野指针及c++指针使用注意点的更多相关文章

  1. NULL指针、零指针、野指针

    1.1.空指针 如果 p 是一个指针变量,则 p = 0; p = 0L; p = '\0'; p = 3 - 3; p = 0 * 17;p=(void*)0; 中的任何一种赋值操作之后, p 都成 ...

  2. 野指针、NULL指针和void*

    一.野指针 “野指针”不是NULL指针,是指向“垃圾”内存的指针. “野指针”的成因主要有三种: (1)指针变量没有被初始化.任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱 ...

  3. 关于空指针NULL、野指针、通用指针 (转)

    reference:https://www.cnblogs.com/losesea/archive/2012/11/16/2772590.html 首先说一下什么是指针,只要明白了指针的含义,你就明白 ...

  4. 关于空指针NULL、野指针、通用指针

    http://www.cnblogs.com/losesea/archive/2012/11/16/2772590.html 首先说一下什么是指针,只要明白了指针的含义,你就明白null的含义了.假设 ...

  5. 空指针、NULL指针、零指针

    1. 空指针.NULL指针.零指针 1.1 什么是空指针常量 0.0L.'\0'.3 - 3.0 * 17 (它们都是“integer constant expression”)以及 (void*)0 ...

  6. void指针和NULL指针

    Void指针和NULL指针 Void指针: Void指针我们称之为通用指针,就是可以指向任意类型的数据.也就是说,任何类型的指针都可以赋值给Void指针. 举例: #include<stdio. ...

  7. C语言指针专题——使用指针要注意这些

    本文为原创,欢迎转发: 欢迎关注微博与微信号:C语言编程技术分享 C语言中,指针的概念有点难懂,使用起来稍微不注意,也会遇到各种问题.在本文中,我列举出了几个使用指针不当的方式,希望朋友们在编程实践中 ...

  8. 第37课 智能指针分析(指针特征操作符( -> 、 *)重载)

    1. 永恒的话题:内存泄漏 (1)动态申请堆空间,用完后不归还 (2)C++语言中没有垃圾回收的机制 (3)指针无法控制所指堆空间的生命周期------------指针是变量,可以指向内存堆空间,但是 ...

  9. C与指针(结构体指针,函数指针,数组指针,指针数组)定义与使用

    类型 普通指针 指针数组(非指针类型) 数组指针 结构体指针 函数指针 二重指针 定义方式 int *p; int *p[5]; int (*p)[5]; int a[3][5]; struct{.. ...

随机推荐

  1. SQL Sever 2012 如何建立数据库连接

    SQL Sever 2012 如何建立数据库连接 一.下载 http://www.microsoft.com/zh-cn/download/details.aspx?id=29062 下载后直接安装即 ...

  2. ORACLE中大数据量查询实现优化

    大数据量查询,对数据库开发者来说,性能问题往往是最需要费尽心机的,借此总结自己优化此类问题的心得与大家分享,以免大家走更多的弯路. 1.使用主键临时表 大数据量表关联查询,是性能开销的主要原因.通过主 ...

  3. GAN

    GAN(Generative Adversarial Nets),产生式对抗网络 存在问题: 1.无法表示数据分布 2.速度 3.resolution太小,大了无语义信息 4.无reference 5 ...

  4. SQLSERVER数据库中的 时间函数

    一.sql server日期时间函数 Sql Server中的日期与时间函数 1.  当前系统日期.时间 select getdate() 2. dateadd  在向指定日期加上一段时间的基础上,返 ...

  5. 深入浅出ExtJS 第五章 树形结构

    5.1 TreePanel的基本使用 //树是一种非常典型的数据结构; 5.1.1 创建一棵树 //树控件有Ext.tree.TreePanel类定义,控件的名称为TreePanel;TreePane ...

  6. Windows命令行中使用SSH连接Linux

    转自 http://www.linuxidc.com/Linux/2014-02/96625.htm 1.下载: openssh for Winodws: 免费下载地址在 http://linux.l ...

  7. js中关于原型的几个方法

    一.isPrototypeOf()方法,判断一个对象是否是另一个对象的原型 function Student(name,age){ this.name=name; this.age=age; } va ...

  8. 验证证书的安装之外部用户PC

      背景:使用一个域外的用户进行登录并验证   1.         用户登录浏览器下载CA证书或者证书链   2.         下载   3.         安装证书   4.         ...

  9. Row_Number实现分页(适用SQL)

    1:首先是 select ROW_NUMBER() over(order by id asc) as 'rowNumber', * from table1 生成带序号的集合 2:再查询该集合的 第 1 ...

  10. AMQ学习笔记 - 19. 问题解决 - 控制Atomikos的日志输出

    概述 在使用Atomikos为ActiveMQ提供JTA支持时,Atomikos在控制台打印了繁琐的日志.这里介绍如何控制Atomikos日志输出的粒度. 解决方案 基于以下三个事实: Atomiko ...