总结了一些指针易出错的常见问题(六)
安全问题与指针误用
声明和初始化指针(初始化失败)
误用指针
释放问题
指针声明:
// 宏定义(仅仅是替换)
#define PINT int*;
PINT ptr1, ptr2;其实是定义 int* ptr1, ptr2;一个指针,一个整型常量。
//typedef 命名已有数据类型(优于宏定义)
typedef int* PINT;
PINT ptr1, ptr2;
宏定义和typedef区别参考:预处理命令与用typedef命名已有类型
// 宏定义 和 typedef区别
#include<stdio.h>
#define INTPTR1 int*
int main()
{
typedef int* INTPTR2;
int a=1;
int b=2;
int c=3;
const INTPTR1 p1=&a;//指针常量,不可修改指向变量的值,但可以改变指向其他变量
const INTPTR2 p2=&b;//常量指针,只读,可修改指向变量的值。
INTPTR2 const p3=&c;//常量指针,只读,可修改指向变量的值。
printf("%d %d %dn",*p1,*p2,*p3);
printf("a=%d b=%d c=%dn",a,b,c);
p1=&c;
*p2=9;
*p3=10;
printf("%d %d %dn",*p1,*p2,*p3);
printf("a=%d b=%d c=%dn",a,b,c);
return 0;
}
使用指针之前未初始化指针(野指针)
处理未初始化指针(不可只依靠检查指针的内容来判断它是否有效)
总是用NULL来初始化指针
用assert函数(用来测试指针是否为空值);assert(pi!=NULL);
若为空值,输出:Assertion failed: pi!=NULL;
用第三方工具
指针的使用问题
缓冲区溢出的几个原因:
访问数组元素时没有检查索引值
对数组指针做指针算术运算时不够小心
用gets这样的函数从标准输入读取字符串
误用strcpy和strcat这样的函数;
测试NULL
用malloc这类函数时一定要检查返回值,否则可能会导致程序非正常终止。
迷途指针(释放指针后却仍然在引用原来的内存,就会产生迷途指针)
超过数组边界访问内存
用下标计算的地址不会检查索引值。
错误计算数组长度
将数组传递给函数时,一定要同时传递数组长度,这个信息帮助函数避免越过数组边界。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void replace(char buffer[],char replacement,size_t size){
size_t count = 0;
while(*buffer!=NULL && count++ <size){
*buffer = replacement;
buffer++;
}
}
int main()
{
char name[8];
strcpy(name,"Alexander");
replace(name,'+',sizeof(name));
printf("%sn", name);
printf("%dn", sizeof(name));
}
错误使用sizeof操作符
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
int name[20];
int *pbuffer= name;
for(int i=0;i<sizeof(name)/sizeof(int);i++)
{
*(pbuffer++)=0;
}
printf("%dn", sizeof(name));
}
一定要匹配指针类型
总是用合适的指针类型来装说句是个好主意。
有界指针
有界指针是指指针的使用被限制在有效的区域内。比如说,现在有一个32个元素的数组,禁止对这个数组使用的指针访问数组前面或后面的任何内存。
字符串的安全问题
字符串相关的安全问题一般发生在越过字符串末尾写入的情况。
指针算术运算和结构体
只对数组使用指针算术运算,因为数组肯定分配在连续的内存块上,指针算术运算可以得到有效的偏移量。不过,不应该将它们用在结构体内,因为结构体的字段可能分配在不连续的内存区域。
函数指针的问题
内存释放问题
重复释放
清除敏感数据(在释放内存之前将敏感数据清空)
小结:
- 0基础搭建Hadoop大数据处理-初识
- 入坑系列之HAProxy负载均衡
- 如何开发自己的搜索帝国之Elasticsearch
- NET中解决KafKa多线程发送多主题的问题
- mysql数据与Hadoop之间导入导出之Sqoop实例
- 如何将mysql数据导入Hadoop之Sqoop安装
- 常见的几种Flume日志收集场景实战
- 教你一步搭建Flume分布式日志系统
- 几十条业务线日志系统如何收集处理?
- 0基础搭建Hadoop大数据处理-编程
- 0基础搭建Hadoop大数据处理-集群安装
- Validation of viewstate MAC failed 解决办法
- springmvc注入类 NoUniqueBeanDefinitionException: No qualifying bean of type [] is defined: expected sin
- springmvc注入类 NoUniqueBeanDefinitionException: No qualifying bean of type [] is defined: expected sin
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- PHP对验证码的认证过程
- Android实现图片加载进度提示
- android shape实现阴影或模糊边效果
- Spring Data JPA主键采用UUID策略
- Android自定义控件之水平圆点加载进度条
- Android屏幕旋转之横屏竖屏切换的实现
- Android Studio连接SQLite数据库的登录注册实现
- Android 获取 usb 权限的两种方法
- Android实现两圆点之间来回移动加载进度
- Android使用第三方库实现日期选择器
- Android Activity向右滑动返回
- 大多数人都不懂的搜索引擎技巧,掌握这几点,提升你的工作效率
- 如何使用Flutter实现58同城中的加载动画详解
- Android Gradle开发指南详解
- Hexo+Github搭建个人博客:Hexo添加分类标签