总结了一些指针易出错的常见问题(六)

  安全问题与指针误用

声明和初始化指针(初始化失败)

误用指针

释放问题

指针声明:

// 宏定义(仅仅是替换)

#define PINT int*;

PINT ptr1, ptr2;其实是定义 int* ptr1, ptr2;一个指针,一个整型常量。

//typedef 命名已有数据类型(优于宏定义)

typedef int* PINT;

PINT ptr1, ptr2;

宏定义和typedef区别参考:浅谈c/c++typedef和#define区别

//  宏定义  和  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 %d\n",*p1,*p2,*p3);
printf("a=%d b=%d c=%d\n",a,b,c);

 p1=&c;
*p2=9;
*p3=10;
printf("%d %d %d\n",*p1,*p2,*p3);
printf("a=%d b=%d c=%d\n",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("%s\n", name);
    printf("%d\n", 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("%d\n", sizeof(name));
} 

  一定要匹配指针类型

总是用合适的指针类型来装说句是个好主意。

  有界指针

有界指针是指指针的使用被限制在有效的区域内。比如说,现在有一个32个元素的数组,禁止对这个数组使用的指针访问数组前面或后面的任何内存。

  字符串的安全问题

字符串相关的安全问题一般发生在越过字符串末尾写入的情况。

  指针算术运算和结构体

只对数组使用指针算术运算,因为数组肯定分配在连续的内存块上,指针算术运算可以得到有效的偏移量。不过,不应该将它们用在结构体内,因为结构体的字段可能分配在不连续的内存区域。

  函数指针的问题

  内存释放问题

重复释放

  

清除敏感数据(在释放内存之前将敏感数据清空)

小结:

时间: 2024-10-16 20:11:49

总结了一些指针易出错的常见问题(六)的相关文章

总结了一些指针易出错的常见问题(三)

指针与字符串 NULL和NUL区别:前者用来表示特殊的指针((void*)0),而NUL是一个char(\0),不可混用. 字符常量:单引号:字符串:双引号: 字符串的声明方式:字面量.字符数组.指针. 字符串字面量池: 字符串初始化 初始化char数组:   char header[]="Media Player"; strcpy函数初始化数组 char header[13]; strcpy(header, "Meadia Player"); 2.初始化char指

总结了一些指针易出错的常见问题(四)

指针与结构体 简介:我们可以使用C的结构体来表示数据结构元素,比如链表或树的节点,指针是把这些元素联系到一起的纽带. typedef struct _person{ char* firstName; char* lastName; char* title; unsigned int age; } Person;/*用点表示法初始化*/ Person person;person.firstName=(char*)malloc(strlen("Emily")+1);stcpy(person

总结了一些指针易出错的常见问题(七)

指针的其他重要内容 主要研究以下问题 指针的类型转换 访问硬件设备 别名和强别名 使用restrict关键字 线程(一是如何用指针在线程之间共享数据这个基本问题:二是如何用指针支持回调函数(一个操作可能会调用某函数来执行任务,如果实际被调用的函数发生了改变,我们称之为回调函数.)) 面向对象技术 转换指针 类型转换是一种基本操作,跟指针结合使用时很有用. 访问有特殊目的的地址: 分配一个地址来表示端口: 判断机器的字节数: 整数转换为整数指针: int num =8; int *pi = (in

总结了一些指针易出错的常见问题(二)

4.指针与数组  一些常见的错误观点是数组和指针是完全可以互换的.尽管数组名字有时候可以当指针来使用,但是数组的名字不是指针. 数组是能用索引访问的同质元素连续集合.(连续是指数组的元素在内存中是相邻的,中间不存在空隙同质是指元素是同一类型) 指针在处理数组时很有用,既可以用指针指向已有的数组,也可以从堆上分配内存然后把这块内存当做一个数组使用. 数组/指针表示法 给数组地址加1实际加了4,也就是整数的长度. #include<iostream> using namespace std; in

总结了一些指针易出错的常见问题(一)

1.认识指针 1.1 指针和内存 C程序在编译后,会以三种形式使用内存: 1)静态/全局内存 静态/全局声明的变量在这里.这些变量从程序开始运行时分配,直到程序终止才消失. 所有函数都能访问全局变量,静态变量的作用域则局限在定义它们的函数内部. 2)自动内存 这些变量在函数内部声明,并且在函数调用时才创建,他们的作用域局限于函数内部, 而且声明周期限制在函数的执行时间内. 3)动态内存 内存分配在堆上,可以根据需要释放,而且直到释放才消失.指针引用分配的内存,作用域 局限于引用内存的指针. 数组

mysql安装及易出错问题解决

.双击.msi 安装包 2.勾选同意,下一步 3.一直 下一步,遇到弹窗选择ok,然后点击Execute 4.check  ok后点击下一步 5.next 6.设置root密码,next 7.无脑next后,来到易出错界面了 - -! (启动服务失败--解决方案:1.卸载完全之前安装的mysql,可能有残留文件导致服务不能启动 2. MySQL安装是出现could not start the service mysql error:0 提示错误,解决方法:  首 先,在管理工具->服务里面将My

jQuery选择器与JavaScript易出错知识点

一.jQuery选择器 基本选择器 1.Id(根据给定的ID匹配一个元素.如果选择器中包含特殊字符,可以用两个斜杠转义.) jQuery代码为$("#myclass") 若有特殊字符则 HTML代码为<span id="myclass[1]" jQuery代码为$("#myclass\\[1\\]") 2.Class(一个用以搜索的类.一个元素可以有多个类,只要有一个符合就能被匹配到) jQuery代码为$(".myclass&q

如何给一个完全不懂的非程序员解释复杂的、耗时的、易出错的软件开发的过程?

简评:相当有趣的一篇文章,教导你如何给非程序员讲清楚最难.最复杂的那些开发问题. 回答这个问题首先你应该解释一下如何泡一壶茶: 烧水 把茶叶放在锅里 当水烧开后,把它倒入锅里 等待 5 分钟 把茶倒进杯子里 喝 现在开始变得有趣了.你需要开始问他们这些问题: 烧水? 水来自哪里? 水壶在哪里呢? 你怎么把水弄到水壶里去呢 你怎么知道放了多少水 如果没有水 / 水壶 / 电怎么办? 如果你的填充传感器失败了怎么办? 如果你的沸腾传感器失败了? 把茶叶放在锅里? 锅在哪里,如果没有一个呢?我们应该在

C提高_day03_一级指针易犯错误模型

1.char *(字符串)做函数参数出错模型分析 建立一个思想:是主调函数分配内存,还是被调用函数分配内存: //不要相信,主调函数给你传的内存空间,你可以写......一级指针你懂了. 但是二级指针,你就不一定懂...抛出......... void copy_str21(char *from, char *to) { if (*NULL = '\0' || *to!='\0') { Printf("func copy_str21() err\n"); return; } for (