避免野指针的产生

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

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. 【Trie】模板(动态指针,静态数组)

    摘自hackbuteer1 Trie树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种.典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计.它的 ...

  2. Kafka删除逻辑

    Kafka的删除逻辑请参见:http://www.cnblogs.com/gaopeng527/p/4950956.html

  3. Part 34 to 35 Talking about multiple class inheritance in C#

    Part 34 Problems of multiple class inheritance Part 35 Multiple class inheritance using interfaces

  4. html meta标签之http-equiv

    摘要:HTTP-EQUIV类似于HTTP的头部协议,它回应给浏览器一些有用的信息,以帮助正确和精确地显示网页内容.常用的HTTP-EQUIV类型有:Content-Type.Refresh .Expi ...

  5. Sass之初识

    Sass is the most mature, stable, and powerful professional grade CSS extension language in the world ...

  6. SQL Server2000安装

    本篇文章介绍了安装SQL Server 2000各版本的软硬件配置要求,企业版安装过程的详细步骤,以及需要注意的事项.其他版本可以参考安装 注意:Windows XP不能装企业版.win2000\wi ...

  7. javascript中的闭包。

    function todo() { var var1 = 1; (function () { var var2 = var1 + 1; alert(var2); })(); } todo(); (fu ...

  8. OSPF系列

    实验一.点对点链路上的OSPF 拓扑图 1. 首先配置好路由器R1接口地址和回环地址 2. 配置路由器R2的接口地址和回环地址 3. 配置路由器R3的接口地址和环回地址 4. 配置R1的OSPF协议 ...

  9. java使用BufferedImage和Graphics实现图片合成

    package com.igoxin.weixin.custom; import java.awt.Graphics; import java.awt.image.BufferedImage; imp ...

  10. java synchronized关键字浅探

    synchronized 是 java 多线程编程中用于使线程之间的操作串行化的关键字.这种措施类似于数据库中使用排他锁实现并发控制,但是有所不同的是,数据库中是对数据对象加锁,而 java 则是对将 ...