新闻详情

新闻详情

首页 / 资讯中心 / 详情

C++使用过程中的溢出问题详解

发布时间:2026/10/1 11:14:38来源:尧图网络
C++使用过程中的溢出问题详解
内容在C/C程序里有一类非常典型的问题那就是溢出问题。现在分别来分析一下常见的数组溢出整数溢出缓冲区溢出栈溢出和指针溢出等。1、数组溢出在C语言中数组的元素下标是从0开始计算的所以对于n个元素的数组a[n] 遍历它的时候是a[0],a[1],...,a[n-1]如果遍历到a[n]数组就溢出了。12345678voidprint_array(inta[],intn){for(inti 0; i n; i){a[i] a[i1];//当i n-1时就发生了数组越界printf(“%d\n”, a[i]);}}上面的循环判断应该改为for (int i 0; i n-1; i)2、整数溢出整数的溢出分为下溢出和上溢出。比如对于有符号的char(signed char)类型来说它能表示的范围为[-128,127]之间而对于无符号的char(unsigned char)来说 它能表示的范围为[0,255]。那么对于下面的代码12345678signedcharc1 127;c1 c11;//发生上溢出c1的值将变为-128signedcharc2 -128;c2 c2-1;//发生下溢出c2的值将变为127unsignedcharc3 255;c3 c31;//发生上溢出c3的值将变为0unsignedcharc4 0;c4 c4-1;//发生下溢出c4的值将变为255从上面的例子可以看出当一个整数向上溢出将会变为最小值而向下溢出将会变为最大值。来看下面的溢出代码该代码负责提供一个小写字母转换表但存在一个整数溢出问题1234567891011voidBuildToLowerTable(void)/* ASCII版本*/{unsignedcharch;/* 首先将每个字符置为它自己 *//*ch为unsigned char无符号数当ch值为UCHAR_MAX ch将会发生向上溢出变为0导致循环无法退出。*/forch0; ch UCHAR_MAX;chchToLower[ch] ch;/* 将大写字母改为小写字母 */for( ch ‘A; ch ‘Z; ch )chToLower[ch] ch a– ‘A;}该代码负责在内存中查找指定的字符ch但也存在一个溢出问题123456789101112void*memchr(void*pv, unsignedcharch,size_tsize ){unsignedchar*pch (unsignedchar*) pv;/*当size的值为0的时候由于size是无符号整数因此会发生下溢出变为一个最大的整数 循环也将无法退出*/while( -- size 0 ){if( *pch ch )return(pch );pch;}return( NULL );}3、缓冲区溢出缓冲区溢出一般是调用了一些不安全的字符串操作函数比如strcpystrcat等这些字符串操作函数在拷贝或者修改目标位置的时候并不判断长度是否会超过目标缓存或者设置参数超过了目标缓存能容纳的大小而造成的溢出问题。1234567891011121314151617181920212223voidfunc1(char* s){charbuf[10];/*此时buf只有10个字节如果传入的s超过10个字节就会造成溢出*/strcpy(buf, s);}voidfunc2(void){printf(Hacked by me.\n);exit(0);}intmain(intargc,char* argv[]){charbadCode[] aaaabbbb2222cccc4444ffff;DWORD* pEIP (DWORD*)badCode[16];*pEIP (DWORD)func2;/*badCode字符串超过了10个字节传递给func1会造成栈上缓冲区溢出而且由于badCode经过精心构造在溢出的时候根据函数的调用约定规则会覆盖栈上的返回地址指向了func2。所以在func1退出的时候会直接调用func2*/func1(badCode);return0;}4、栈溢出无论是内核栈还是应用层的栈都是有一定大小限制的。如果在栈上分配的空间大于了这个限制就会造成栈大小溢出破坏栈上的数据。比如局部变量过多或者递归调度嵌套太深都会造成栈溢出。比如1234567891011121314intinit_module(void){charbuf[10000];//buf[]分配在栈上但10000的空间超过了栈的默认大小8KB。//所以发生溢出memset(buf,0,10000);printk(kernel stack.\n);return0;}voidcleanup_module(void){printk(goodbye.\n);}MODULE_LICENSE(GPL);//应用栈的大小对少内核栈的大小多少什么时候容易栈溢出5、指针溢出一块长度为size大小的内存bufferbuffer的首地址为p那么buffer最后一个字节的地址psize-1而不是psize。如果写成了psize就会造成溢出比如下面的代码123456789101112void*memchr(void*pv, unsignedcharch,size_tsize ){unsignedchar*pch ( unsignedchar* )pv;unsignedchar*pchEnd pch size;while( pch pchEnd ){if( *pch ch )return( pch );pch ;}return( NULL );}上面的代码用于查找内存中特定的字符位置。对于其中的while循环平时执行似乎都没有任何问题。但是考虑一种特别情况即pv所指的内存位置为末尾若干字节那么因为pchEnd pchsize所以pchEnd指向最后一个字符的下一个字节将会超出内存的范围即pchEnd所指的位置已经不存在。知道了问题所在那么可以将内存的结尾计算方式改为1234567pchEnd pv size – 1;while( pch pchEnd ){if( *pch ch )return( pch );pch ;}pchEnd指向了最后一个字节。但是检查循环内部的执行情况可知由于pch每增加到pchEnd1时都会发生上溢。因此循环将无法退出。 于是可以将程序修改为下面的代码。将用size变量来控制循环的退出。这样就不会存在任何问题了。1234567891011void*memchr(void*pv, unsignedcharch,size_tsize ){unsignedchar*pch ( unsignedchar* )pv;while( size -- 0 ){if( *pch ch )return( pch );pch ;}return( NULL );}大家知道--size的效率一般比size--的效率高。那么是否可以将循环的判断条件改为下面的语句呢while --size 0 ……实际上这是不行的。因为当size0时由于size是无符号数那么它将发生下溢变成了size所能表示的最大正数循环也将无法退出。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

全栈工程师和前端工程师的区别 2026/10/1 12:46:01

全栈工程师和前端工程师的区别

它牵扯到的那个情况, 是关于一种叫做其他这样的软件的。课程简介:全栈工程师需要同时兼顾前端开发和后端开发工作, 而前端工程师则专注于前端部分的工作, 这是他们之间的主要区别。无论从工作场景还是从学习过程来看, 全栈工程师所涉及的内容范围都要广泛一些, 而前…

阅读更多 →
VCS/Verdi许可激活 2026/10/1 12:46:01

VCS/Verdi许可激活

摘要 首先,本文只展示怎么激活VCS/Verdi,除此之外软件安装比较简单,自行安装即可。 因为网上对于EDA工具的安装教程还是比较分散的,或者是对小白不太友好,看起来难免云里雾里,之前本人一直是饭来张口的状…

阅读更多 →
基于U-Net的COVID肺部感染分割实战:从数据集到训练全流程 2026/10/1 12:45:55

基于U-Net的COVID肺部感染分割实战:从数据集到训练全流程

简介:这份资源面向医学图像分割方向的算法学习者与研究者,提供约2500张256256分辨率的肺部感染(COVID)图像分割数据,前景标注为感染区域,mask采用前景255的二值图像,便于直观观察与训练。数据在…

阅读更多 →
JMeter脚本录制实战:HTTPS录制、参数化关联与压测排错 2026/10/1 12:45:54

JMeter脚本录制实战:HTTPS录制、参数化关联与压测排错

做 JMeter 脚本录制,真正让人头疼的往往不是找不到按钮,而是录完以后脚本跑不起来:登录态丢了、Token 对不上、静态资源一大堆、HTTPS 还弹证书警告。尤其是接手一个已有系统,接口文档不全,前端参数藏得深,…

阅读更多 →
逻辑严谨吗?8款AI写作辅助软件榜单,毕业论文轻松搞定! 2026/10/1 12:45:54

逻辑严谨吗?8款AI写作辅助软件榜单,毕业论文轻松搞定!

写论文时是不是总感觉思路混乱,无从下手?查重一遍又一遍,结果还是不理想?格式调整让人头大,时间精力都耗在细节上? 别担心!AI论文写作工具正在改变学术写作的规则。本文将围绕内容逻辑性、文献…

阅读更多 →
拉链表回撤实操指南:重建式SQL、边界处理与下游补偿 2026/10/1 12:45:48

拉链表回撤实操指南:重建式SQL、边界处理与下游补偿

凌晨一点半,运维群突然弹出一条消息:“用户维度拉链表出现大量生命周期错乱,领导要求把表回撤到7月1日零点。”我看完愣了几秒,因为就在前一天,月度指标刚重算完。拉链表回撤这件事,在大数据平台上属于“平…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉