C语言中常见的内存踩踏现象
此篇文章在2024年7月15日被记录
程序员在C编码时需要尽量考虑所有的异常情况,否则解决问题需要花费制造问题的数倍
1、数组操作越界,造成相邻内存中的数据踩踏
在下面示例代码中,arr_a[i] = 10
越界访问造成了arr_b中的数据被修改
uint8_t arr_a[5] = {0,1,2,3,4} ;
uint8_t arr_b[5] = {4,3,2,1,0} ;
void log_arr(uint8_t *arr , uint32_t len)
{
for(int i = 0 ; i < len ; i++ )
{
printf("\r\n arr[%d] : %d ",i , arr[i]);
}
printf("\r\n");
}
int main() {
printf("step1:\r\n");
printf("arr_a:\r\n");
log_arr(arr_a,sizeof(arr_a));
printf("arr_b:\r\n");
log_arr(arr_b,sizeof(arr_b));
int i = 5 ;
arr_a[i] = 10 ;
printf("step2:\r\n");
printf("arr_a:\r\n");
log_arr(arr_a,sizeof(arr_a));
printf("arr_b:\r\n");
log_arr(arr_b,sizeof(arr_b));
return 0;
}
打印输出:
step1:
arr_a:
arr[0] : 0
arr[1] : 1
arr[2] : 2
arr[3] : 3
arr[4] : 4
arr_b:
arr[0] : 4
arr[1] : 3
arr[2] : 2
arr[3] : 1
arr[4] : 0
step2:
arr_a:
arr[0] : 0
arr[1] : 1
arr[2] : 2
arr[3] : 3
arr[4] : 4
arr_b:
arr[0] : 10
arr[1] : 3
arr[2] : 2
arr[3] : 1
arr[4] : 0
2、临时变量踩内存
在下面的示例代码中,对array的越界操作造成了局部变量a被修改,这种问题通常较难发现,因为临时变量是在栈区存在的,因此被踩时会造成先压栈的数据修改。
int main() {
uint8_t a = 10 ;
printf("step1:a=%d\r\n",a);
uint8_t array[10] ;
memset(array,0x00,11);
printf("step2:a=%d\r\n",a);
return 0;
}
打印输出:
step1:a=10
step2:a=0
3、内存泄漏问题
下面的示例代码中,动态申请的内存在未被释放的情况下重新申请,导致第一次申请的长度为5的内存长度永远不能被释放或者使用。短时间内虽然没有问题,但是随着时间推移,可能会造成内存被占满死机
#include <stdlib.h>
int main() {
char *p1;
p1 = malloc(5);
strcpy(p1, "1234");
printf("p1:%s\r\n",p1);
p1 = malloc(10);
strcpy(p1, "123456789");
printf("p1:%s\r\n",p1);
free(p1);
return 0;
}
4、栈内存申请过大问题
在单片机系统中,栈空间往往较小,尽量避免使用较大的临时变量,否则可能会直接进入硬件错误
#include <stdlib.h>
int main() {
uint32_t a[10*1024];
memset(a,0,sizeof(a));
printf("a[0]:%d",a[0]);
return 0;
}
5、类型强制转换造成的错误
有时对数组进行强制类型转换后,对数组进行不合理索引操作可能会造成内存错误。
#include <stdlib.h>
uint8_t a[8] = {0};
uint8_t b[8] = {0};
int main() {
uint16_t *p = (uint16_t *)a;
p[0] = 0x0102;
p[1] = 0x0102;
p[2] = 0x0102;
p[3] = 0x0102;
p[4] = 0x0102;
p[5] = 0x0102;
p[6] = 0x0102;
p[7] = 0x0102;
for( int i = 0 ; i < sizeof(a) ; i++)
{
printf("a[%d] = %d\r\n" , i,a[i]);
}
for( int i = 0 ; i < sizeof(b) ; i++)
{
printf("b[%d] = %d\r\n" , i,b[i]);
}
return 0;
}
结果打印:
a[0] = 2
a[1] = 1
a[2] = 2
a[3] = 1
a[4] = 2
a[5] = 1
a[6] = 2
a[7] = 1
b[0] = 2
b[1] = 1
b[2] = 2
b[3] = 1
b[4] = 2
b[5] = 1
b[6] = 2
b[7] = 1