电子产业一站式赋能平台

PCB联盟网

搜索
查看: 34|回复: 0
收起左侧

MCU软件开发使用指针有哪些坑?

[复制链接]

652

主题

652

帖子

5232

积分

四级会员

Rank: 4

积分
5232
发表于 2024-11-15 08:02:00 | 显示全部楼层 |阅读模式

mll0zxurs5v64078530501.gif

mll0zxurs5v64078530501.gif

! G8 @3 V5 a8 j7 F, u' B# |点击上方蓝色字体,关注我们" W' ]/ K* i+ X. \( M! p
在MCU软件开发中,使用指针虽然可以提高程序的灵活性和性能,但也存在许多潜在的坑,尤其是在资源受限的嵌入式系统中。* M* W# w% E( l7 B
6 c5 q0 B+ |+ t; J6 N/ H; l

wa3j31rcgam64078530602.png

wa3j31rcgam64078530602.png

4 _- {- K' Q, H! N0 H* `/ o0 f7 ?: k8 G9 e7 L
1
& V+ t/ e6 }9 g+ w9 U空指针访问
# `9 x+ ^8 c1 L- _1 @空指针(NULL指针)没有指向任何有效的内存地址,试图访问空指针会导致程序崩溃或异常行为。
6 W7 K0 W# c: I
5 P. j1 G7 z" n  P6 J/ H例如以下错误代码:1 n" w. D5 d' C( m

* f7 }* g$ @! t- X! s3 J! l
  • int *ptr = NULL;*ptr = 10;  // 空指针访问,可能导致崩溃' g# L7 P7 s; |! E* \8 I. J! H
    在使用指针前确保它已经正确初始化,并检查指针是否为NULL:' _) W4 e4 W5 w- I
    " j/ N3 I, B% w: m) J& v6 C) b) H7 V
  • if (ptr != NULL) {    *ptr = 10;}
      |$ I9 ?( B* h3 r8 w* t2
    4 ~; E( I- c; I0 P, H0 @2 o, i9 l1 _野指针(未初始化的指针)3 G; c* [8 D% @- {# F* Q
    未初始化的指针指向一个随机的内存地址,可能会覆盖其他重要的数据或导致程序不可预测的行为。
    ( x9 O( R+ }2 h4 j' ?/ w* w5 G8 J6 `2 K" w
    例如以下错误代码:, `! `  h* T& x# z* X- N$ `! j  B

    % }- I$ I! R0 H. e; l+ x
  • int *ptr;*ptr = 10;  // 野指针访问,指向未知内存& ~: W4 c6 D0 W0 w' ^' ~
    始终在声明指针时初始化:
    - S# u- C$ O8 }- l+ ^
    " T( ]: a9 e8 l! H
  • int *ptr = NULL;
    2 j. N8 T) l& e4 m7 c* _0 @7 B3
    ) O) s$ ]6 U6 P+ T0 o4 K% a指针越界
    3 |6 P/ y) L4 c1 @/ E( V+ h指针越界意味着指针超出它所指向的数组或内存块的边界,这会导致访问不属于程序的内存区域,从而产生不可预知的结果。9 O( l4 N9 x, L, L% a- V( `- L
    ) x% @! ^- ^0 g' n9 k+ N
    例如以下错误代码:. {* V7 O, d- p3 P( X8 K

    ) i2 m% H! j1 q0 |5 V* h0 z
  • int arr[5] = {1, 2, 3, 4, 5};int *ptr = arr;ptr += 6;  // 超出数组边界*ptr = 10; // 可能导致崩溃
    2 R% ~3 T4 u9 l* u- F确保指针操作不会超出合法的内存范围。可以使用数组大小控制指针的移动:
    " b* ~8 m$ |$ d- c( r
    1 t) [9 A6 N2 q- S8 k  R: V
  • for (int i = 0; i 5; i++) {    *(ptr + i) = i;}. X3 J  q. u; {8 q5 @- A8 i
    4/ i) f# `6 S6 ~2 m) A
    内存泄漏2 ^7 e$ d0 I( u; I$ @" o4 J
    在使用动态内存分配时,忘记释放内存可能导致内存泄漏,这在MCU开发中尤为关键,因为嵌入式系统的内存资源非常有限。
    0 h0 i) u2 v4 b# G- q: H8 t
    6 |) ]0 J7 R7 ^: a: ?7 H) g例如以下错误代码:
    & Z- W  z2 E9 M; k5 w
    9 S0 d* F( i$ d
  • int *ptr = (int *)malloc(10 * sizeof(int));  // 没有释放分配的内存
    0 s# ?% y) o3 \. M0 p2 L使用完动态分配的内存后,应及时释放:
    / D0 h: i  T/ {1 C
    # U. @! g: E5 C5 q* a8 `; K
  • free(ptr);ptr = NULL;  // 释放后将指针置为NULL,避免悬空指针
    + H. Z5 {! `/ K$ K+ Q, @. N5; [5 w! V5 D5 m2 p- j2 M
    悬空指针
    ) {/ v9 N2 ?: ^! D悬空指针指向已释放的内存。即使内存已释放,指针仍然持有该地址,但这个地址可能已被重新分配给其他变量或程序。: q0 \4 W# n; x. t; c

    ' a3 y" a7 U& ^0 c例如以下错误代码:3 H+ W9 _/ T4 L: l& F( l7 q

    3 }, b8 A+ }& {* C9 w
  • int *ptr = (int *)malloc(10 * sizeof(int));free(ptr);  // 释放内存*ptr = 10;  // 悬空指针访问,可能导致崩溃
    * \) `; y, Q: \2 D- m释放内存后将指针设为NULL,避免对悬空指针的使用:
    / ^" I. q5 K! \* }( s! I8 X! ], X. ?" z/ n
  • free(ptr);ptr = NULL;
    % f* F) E+ K+ T% ]& P$ R6# S& T% |) y3 v
    指针类型不匹配. d# `( \5 P" }" ?* K( c! p
    在进行指针类型转换或操作时,如果类型不匹配,可能会导致数据解释错误,尤其是在访问外设寄存器或硬件地址时。/ U; R$ L+ _* k# p
    + F) N* T: @2 T, f7 m% t  Q  w- ^
    例如以下错误代码:- X! B' E  ^( h. I  A
    ' |0 B8 a. [- {4 p9 v7 O+ H$ H
  • char *ptr = (char *)malloc(sizeof(int));*ptr = 0xFF;  // 操作4字节的int时,只改变了1字节8 U, g' v+ f7 |
    确保指针类型与所操作的数据类型一致,尤其在寄存器访问时要注意对齐问题:
      B2 _6 b3 D7 L) P
    + Z5 H( Q% @4 P  M5 V4 `
  • int *ptr = (int *)malloc(sizeof(int));*ptr = 0xFFFFFFFF;  // 确保类型匹配
    ( b  D: f; I, L3 }" q7 v7
    ' Y* O: T+ c" w# w" V+ I. ^; ~多任务环境中的指针访问  V7 i) s# m2 Q8 n

    + L  c) n. p& D* U6 j9 s在RTOS或多任务系统中,不同任务之间共享同一个指针,可能导致竞争条件或数据一致性问题,尤其是在一个任务修改指针指向的内存时,另一个任务也在访问它。9 l  S3 z: n+ s( E( |
    4 V8 B/ `: s6 |( _! w3 E
    例如以下错误代码:4 e/ ?& ~) V) W' I4 d9 a0 F
    + f5 N/ `8 w' }, F+ \# U" S& B
  • int *shared_ptr;// 任务1修改*shared_ptr = 10;// 任务2同时访问int val = *shared_ptr;  // 数据不一致
    ( j& A9 l' f" `% x在多任务环境中,使用互斥锁或信号量来保护共享指针:
    ) |! D/ Z+ Z9 {7 h4 |
    3 @4 T4 N0 B: o  G$ O
  • // 任务1osMutexWait(mutex_id, osWaitForever);*shared_ptr = 10;osMutexRelease(mutex_id);) ^. d( |! g4 V5 n8 a; ^
    // 任务2osMutexWait(mutex_id, osWaitForever);int val = *shared_ptr;osMutexRelease(mutex_id);- T9 Q: B( X, Q/ B& E5 a+ B
    8* f! \1 v0 }4 [3 {& T( V3 q
    对齐问题7 J: {$ P$ O) }  _+ r- v% z* d5 o
    在MCU中,某些处理器要求数据访问时必须按照特定的字节对齐。
    " f0 C0 s0 P( b5 }  c0 m. ~# b- q2 r1 S6 l: r
    如果使用未对齐的指针访问内存,可能导致总线错误或数据访问效率低下。0 {  u) t9 V* I3 q

    ; J( B& u5 m7 |. ^2 k1 Z  P例如以下错误代码:( @4 j* E- G, X# f

    - O1 j2 r1 E+ z, @
  • char data[10];int *ptr = (int *)&data[1];  // 可能未按4字节对齐*ptr = 0x12345678;           // 引发访问错误) ^, s" @# h( g, R) U' a
    确保指针访问的数据地址是按照处理器的要求对齐的:
    3 l6 b/ r1 {1 v6 f& z! o
    " N9 Z% H6 v( H% Q. a4 {
  • int *ptr = (int *)((uintptr_t)(data + 3) & ~0x3);  // 强制对齐: W/ o! h  B& X1 t- ?  y
    MCU开发中的指针使用需要格外小心,特别是在内存有限和资源受限的情况下。: G% a- V& Y- W3 o+ t. [1 D- f/ `
    - ^- m3 U+ u- z3 r: n
    通过良好的编码习惯(如初始化指针、检查NULL、使用互斥保护共享数据等),可以避免大多数与指针相关的问题。
    ; |) P( J+ S. Z, `- e9 f; r

    lzynsq1ffbf64078530702.jpg

    lzynsq1ffbf64078530702.jpg
    0 ?0 ~! H% L' j' \, T

    evbxlres0nc64078530802.gif

    evbxlres0nc64078530802.gif

    # _6 W& r. |' E! R4 I& h7 o点击阅读原文,更精彩~
  • 回复

    使用道具 举报

    发表回复

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则


    联系客服 关注微信 下载APP 返回顶部 返回列表