当前位置: 首页 > news >正文

高效C/C++之九:Coverity修复问题:关于数组操作 和 内存操作

【关注我,后续持续新增专题博文,谢谢!!!】

上一篇我们讲了

        这一篇我们开始讲 高效C/C++之九:Coverity修复问题:关于数组操作 和 内存操作

目录

【关注我,后续持续新增专题博文,谢谢!!!】

一、关于数组操作

    2.1:使用没有初始化的下标变量

    2.2 :下标越界操作

二、:关于内存操作

    2.1:申请和释一一对应

    2.2 :释放后切勿再访问,赋nullptr

    2.3 :关于 delete 和 delete [ ]

    2.4 :对象释放之后再次释放

    2.5 :c/c++内存分配

 

【关注我,后续持续新增专题博文,谢谢!!!】


一、关于数组操作

    2.1:使用没有初始化的下标变量

使用没有初始化的下标变量,进行写入,可能会写入一些系统内存,导致安全风险。

习惯对变量赋值的用法是,先判断变量是否是某个初值,然后进行相关操作,将返回值赋给变量。

异常代码
uint size;
buff[size] = 7;
正确代码
uint size = 0;
buff[size] = 7;

    2.2 :下标越界操作

数组下标越界,读写非法内存,造成内存踩踏,数组下标越界不会被编译器检查到,且会在运行时导致程序随机崩溃。

使用下标之前,需要校验下标是否在数组长度的范围内。

异常代码
char c = buff[offset];
正确代码
if ((offset >= 0) && (offset < size)) {char c = buffer[offset];
} else {return -1;
}

二、:关于内存操作

    2.1:申请和释一一对应

1:栈空间会随着生命周期的消失而消失,堆空间则不会,因为申请的内存一定要去释放;malloc 和 free、new 和 delete、new[]和 delete[] 申请和释放要一一对应;

    2.2 :释放后切勿再访问,赋nullptr

释放的内存包括调用free()、delete()释放的堆内存和函数执行完后自行释放的栈内存,这两类已释放内存如果还被访问,会存在很大风险。

所以我们在释放后,要给指针变量赋值为nullptr,避免野指针,就算再释放nullptr,也不会有问题。

    2.3 :关于 delete 和 delete [ ]

一维数组
int *array=new int [m];
delete [] array;
二维数组
int **array
array = new int *[m];
for (int i=0; i<m; i++ ) {array[i] = new int [n]  ;
}for( int i=0; i<m; i++ ) {delete [] array[i];
}
delete [] array;

对于简单的数组来说 delete [] array 和 delete array,释放效果相同,原因在于:分配简单类型内存时,内存大小已经确定,系统可以记忆并且进行管理,在析构时,系统并不会调用析构函数, 它直接通过指针可以获取实际分配的内存空间,哪怕是一个数组内存空间

class Obj
{public:Obj() { cout << "construct function" <<endl; }~Obj() { cout << "destruct function" <<endl; }
};Obj* ObjArray = new Obj[4];
//1 调用使用类对象的析构函数,2 释放了 ObjArray 指针指向的全部内存空间
delete [] ObjArray;//1 释放了 ObjArray 指针指向的全部内存空间 2 只调用了 ObjArray[0]对象的析构函数
delete ObjArray; 

    2.4 :对象释放之后再次释放

重复关闭内存(double-free)会导致内存管理器出现问题。重复释放内存在一定情况下,有可能导致"堆溢出"漏洞,可以被用来执行恶意代码,具有很大的安全隐患。

所以我们在释放后,要给指针变量赋值为nullptr,避免野指针,就算再释放nullptr,也不会有问题。

    2.5 :c/c++内存分配

int g_int1 = 1;
int g_int2 = 0;
int g_int3;
static int g_sInt1 = 1;
static int g_sInt2 = 0;
static int g_sInt3;int main() {int int1 = 1;int int2 = 0;int int3;static int s_int1 = 1;static int s_int2 = 0;static int s_int3;char *p;char *p1;char cStr[20] = "hello world!";char cStr1[10];char cStr2[10];char *qStr = "hello world!";char *qStr1 = "world hello!";p = (char *)malloc(100);p1 = (char *)malloc(100);/* heap area start */printf("p1                  %p, %d\n", p1, p1);printf("p                   %p, %d\n", p, p);/* heap area end /* stack area start */printf("int1                %p, %d\n", &int1, &int1);printf("int2                %p, %d\n", &int2, &int2);printf("int3                %p, %d\n", &int3, &int3);printf("cStr                %p, %d\n", cStr, cStr);printf("cStr1               %p, %d\n", cStr1, cStr1);printf("cStr2               %p, %d\n", cStr2, cStr2);/* stack area end *//* static area start *//* data segment start */printf("s_int1              %p, %d\n", &s_int1, &s_int1);printf("g_sInt1             %p, %d\n", &g_sInt1, &g_sInt1);printf("g_int1              %p, %d\n", &g_int1, &g_int1);/* data segment end *//* bss segment start */printf("s_int3              %p, %d\n", &s_int3, &s_int3);printf("s_int2              %p, %d\n", &s_int2, &s_int2);printf("g_sInt3             %p, %d\n", &g_sInt3, &g_sInt3);printf("g_sInt2             %p, %d\n", &g_sInt2, &g_sInt2);printf("g_int3              %p, %d\n", &g_int3, &g_int3);printf("g_int2              %p, %d\n", &g_int2, &g_int2);/* bss segment end *//* const segment start */printf("world hello!        %p, %d\n", &"world hello!", &"world hello!");printf("qStr                %p, %d\n", qStr1, qStr1);printf("hello world!        %p, %d\n", &"hello world!", &"hello world!");printf("qStr                %p, %d\n", qStr, qStr);    /* const segment end *//* static area end *//* text area start */printf("code addr start:    %p, %d\n", &main, &main);/* text area start */free(p);free(p1);return 0;
}

【关注我,后续持续新增专题博文,谢谢!!!】

下一篇讲解

相关文章:

  • Google 发布 Gemini 2.5 Pro Preview (I/O Edition),具有增强的编程能力
  • Java三大基本特征之多态
  • sherpa:介绍
  • 注解的定义
  • 基于STM32、HAL库的CH340N USB转UART收发器 驱动程序设计
  • Linux云计算训练营笔记day04(Rocky Linux中的命令)
  • Vue知识框架
  • 国产激光二极管厂家
  • 低光图像增强新色彩空间HVI:技术突破与创新解析(HVI: ANewColor Space for Low-light Image Enhancement)
  • 云计算运维
  • SQL知识点总结
  • 解决正点原子IMX6U开发板Buildroot构建qt根文件系统解压后,没有库文件
  • ​无线手持吸尘器无刷BLDC驱动方案功能介绍---【其利天下】
  • 单片机-STM32部分:9、定时器
  • ui生成提示词
  • pm2 list查询服务时如何通过name或者namespace进行区分
  • 笔试专题(十六)
  • 电力电子simulink练习09:复合控制_闭环控制与开环控制结合
  • 高频交直流传感技术在射频器件与微系统测试中的创新实践
  • Windows命令行软件管理器:Chocolatey
  • 习近平会见古共中央第一书记、古巴国家主席迪亚斯-卡内尔
  • 远离军事前线的另一面暗斗:除了“断水”,印度还试图牵制对巴国际援助
  • 人民日报整版调查:中小学春秋假,如何放得好推得开?
  • 洛杉矶奥组委确认2028年奥运会和残奥会开闭幕式场地
  • 苹果Safari浏览器上的搜索量首次下降
  • 美联储如期按兵不动,强调“失业率和通胀上升的风险均已上升”(声明全文)