溢出问题:数组溢出,整数溢出,缓冲区溢出,栈溢出,指针溢出

您所在的位置:网站首页 c语言如果数据溢出怎么办 溢出问题:数组溢出,整数溢出,缓冲区溢出,栈溢出,指针溢出

溢出问题:数组溢出,整数溢出,缓冲区溢出,栈溢出,指针溢出

2024-07-10 19:49| 来源: 网络整理| 查看: 265

在C/C++程序里有一类非常典型的问题,那就是:溢出问题。一般在笔试题里,这类问题会以程序改错或者安全问题出现。现在分别来分析一下常见的数组溢出,整数溢出,缓冲区溢出,栈溢出和指针溢出等。

(1)数组溢出

在C语言中,数组的元素下标是从0开始计算的,所以,对于n个元素的数组a[n], 遍历它的时候是a[0],a[1],...,a[n-1],如果遍历到a[n],数组就溢出了。 void print_array(int a[], int n){    for (int i = 0; i < n; i++)     {        a[i] = a[i+1];//当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]。那么,对于下面的代码:signed char c1 = 127;c1 = c1+1;//发生上溢出,c1的值将变为-128signed char c2 = -128;c2 = c2-1;//发生下溢出,c2的值将变为127unsigned char c3 = 255;c3 = c3+1;//发生上溢出,c3的值将变为0unsigned char c4 = 0;c4 = c4-1;//发生下溢出,c4的值将变为255从上面的例子可以看出,当一个整数向上溢出,将会变为最小值,而向下溢出,将会变为最大值。

来看下面的溢出代码,该代码负责提供一个小写字母转换表,但存在一个整数溢出问题:void BuildToLowerTable( void ) /* ASCII版本*/{    unsigned char ch;    /* 首先将每个字符置为它自己 */    /*ch为unsigned char,无符号数,当ch值为UCHAR_MAX, ch++将会发生向上溢出,变为0,导致循环无法退出。*/    for (ch=0; ch = 0 ) …… 

实际上这是不行的。因为当size=0时,由于size是无符号数,那么它将发生下溢,变成了size所能表示的最大正数,循环也将无法退出。 

(6)字符串溢出

我们已经知道,字符串是'\0'结尾的。如果字符串结尾忘记带上'\0',那么就溢出了。注意,strlen(p)计算的是字符串中有效的字符数(不含’\0’)。考察下面拷贝字符串的代码,看看有什么问题没呢?

 

char *str = “Hello, how are you!”;

char *strbak = (char *)malloc(strlen(str));

if (NULL == strbak)

{

//处理内存分配失败,返回错误

}

strcpy(strbak, str);

......

 

显然,由于strlen()计算的不是str的实际长度(即不包含’\0’字符的长度),所以strbak没有结束符’\0’,而在C语言中,’\0’是字符串的结束标志,所以是必须加上的,否则会造成字符串的溢出。所以上面的代码应该是:

 

char *str = “Hello, how are you!”;

char *strbak = (char *)malloc(strlen(str)+1);

if (NULL == strbak)

{

    //内存分配失败,返回错误

}

strcpy(strbak, str);

 

同样对于strncpy也可能会造成字符串溢出。strncpy函数原型:

char * strncpy(char *dest, char *src, size_t n); 

功能:将字符串src中最多n个字符复制到字符数组dest中(它并不像strcpy一样遇到'\0'才停止复制,而是等凑够n个字符才停止复制),返回指向dest的指针。要求:如果n > dest串长度,dest栈空间溢出产生崩溃异常。该函数注意的地方和strcpy类似,但是n值需特别注意 :

 

1)src串长度dest串长度  如果n =dest串长度,则dest串没有'\0'字符,会导致字符串溢出,输出会有乱码。如果不考虑src串复制完整性,可以将dest最后一字符置为'\0'。所以,一般把n设为dest(含'\0')的长度(除非将多个src复制到dest中)。当2)中n=dest串长度时,定义dest为字符数组,因为这时没有'\0'字符拷贝。

  

思考题:

1,分析下面程序运行情况,有什么问题呢?请深入分析1 void main(void)2 {3     char x,y,z;4     int i;5     int a[16];6     for(i=0;i"dlrow olleh"。试分析存在的问题。void ReverseString(char * str){    int n;    char c;    n = strlen(str);    for (int i = 0; i < n/2; i++)    {        c = str[i];        str[i] = str[n-i];        str[n-i] = c;    }}3,下面代码用于将一个char类型的数求反。试分析下面代码问题。signed char func(signed char c){    return c*(-1);}



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3