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
posted @ 2024-12-13 15:26  田帅康学习笔记  阅读(0)  评论(0编辑  收藏  举报