1. 类型转换导致的内存溢出问题
C语言虽然同时支持有符号数据和无符号数据类型。但是最好不要随意用无符号数据类型。因为在隐士类型转换情况下,如果是有符号数据转换为无符号数据类型,程序会出现意想不到的bug。
下边列举一个有符号数据,隐士转换为无符号数据类型后,导致的内存错误。
直接撸代码:
#include<stdio.h>
float sum_elements(float a[], unsigned length)
{
int i;
float result = 0;
for (i=0; i<=length -1; i++)
{
printf("when the length is zero, there will be memory issue\n");
result += a[i];
}
printf("the result is %f\n", result);
return result;
}
int main()
{
float array[5] = {1.0, 2.0, 3.0, 4.0, 5.0};
sum_elements(array, 0);
}
问题分析
运行上边代码,因为length传递的值是0,length-1 就变成有符号值,而length定义的是无符号值,这里会发生一个隐士转换,然后length-1就变成的无符号数的最大值,所以for循环是一直满足条件的,这个时候数组a就会出现内存越界的情况。从而导致程序崩溃。
改进措施
将sum_elements的参数length的类型改为signed类型。或者,将小于等于改成<length, 不需要length-1;然后问题就迎刃而解。有木有很神奇!!!
案例2
C++案例
//this function is buggy
unsigned i = 3;
cout << i * -1 << endl;
问题分析
先说结果,4294967293.
因为i*(-1)的值隐士转换成了unsigned,所以就是3 * (0XFFFF FFFF),然后值溢出,除以2^32取模,结果就是4294967293.
2. 数组越界的问题
直接show代码
下边的代码有可能陷入死循环,为什么?
#include <stdio.h>
#include <stdint.h>
int main()
{
uint16_t arr_p[5], i;
for (uint16_t i = 1; i <= 5; ++i)
{
arr_p[i] = 0;
}
return 0;
}
解析
栈空间的生长方向是向上的(从高地址->低地址),数组arr_p[5]已经越界了,刚好有可能越界的指针指向了i的地址空间,这个时候i的值清零,所以for循环一直满足条件,将无限循环下去。