본문 바로가기
코딩취미/C,C++

IAR 컴파일러 경고 해결: undefined behavior : the order of volatile accesses is undefined

by 브링블링 2025. 5. 2.
반응형

IAR 컴파일러 경고 해결: undefined behavior : the order of volatile accesses is undefined

임베디드 C 개발을 하다 보면 IAR 컴파일러에서 아래와 같은 경고를 접하는 경우가 있습니다:

Warning[Pa080]: undefined behavior : the order of volatile accesses is undefined in this statement
 

처음 보는 분들에게는 다소 생소할 수 있지만, 이 경고는 정의되지 않은 동작(undefined behavior) 이 발생할 가능성이 있음을 알려주는 중요한 신호입니다. 이 글에서는 해당 경고의 원인과 해결 방법을 예제와 함께 쉽게 설명드리겠습니다.


🔍 문제 상황 예시

아래는 문제가 되는 코드입니다:

cprintf("a = %d, b = %d\r\nmsec = %d, count = %d\r\n", var_a, var_b, msec, count);
 

이 코드에서 var_a, var_b, msec, count 중 하나라도 volatile 키워드로 선언되어 있다면, IAR은 위와 같은 경고를 발생시킵니다.


💡 volatile이란?

volatile은 C 언어에서 값이 예측할 수 없이 변경될 수 있는 변수에 사용하는 키워드입니다.
예를 들어, 하드웨어 레지스터, 인터럽트 핸들러에서 변경되는 변수 등이 이에 해당합니다.

volatile int count;
 

이 변수는 언제 어떤 이유로 값이 바뀔지 모르므로, 컴파일러는 항상 메모리에서 직접 읽고 쓰도록 강제합니다.

반응형

⚠️ 경고의 근본 원인

C 언어에서는 함수 인자들의 평가 순서(evaluation order) 가 정의되어 있지 않습니다.

즉, 아래 코드에서:

cprintf("a = %d, b = %d\r\nmsec = %d, count = %d\r\n", var_a, var_b, msec, count);
 

컴파일러가 var_a, var_b, msec, count를 어떤 순서로 읽을지 보장하지 않으며,
이 변수들이 volatile이면 이는 잠재적인 정의되지 않은 동작이 됩니다.


✅ 안전한 해결 방법

volatile 변수의 값을 임시 변수에 먼저 저장한 뒤, 그 값을 사용하도록 변경하면 경고를 없앨 수 있습니다:

int a = var_a;
int b = var_b;
int t = msec;
int c = count;

cprintf("a = %d, b = %d\r\nmsec = %d, count = %d\r\n", a, b, t, c);
 

이렇게 하면:

  • volatile 변수는 명확한 순서로 한 번씩만 접근되며
  • cprintf 함수에는 일반 변수만 전달되므로 경고가 사라집니다.

🧠 추가 설명: C의 평가 순서와 undefined behavior

C 언어는 다음과 같은 경우 평가 순서를 보장하지 않습니다:

  • 함수 인자 (func(a(), b()))
  • 복합 표현식 (x = y++ + y++)

특히 volatile 변수는 외부에서 변경될 수 있기 때문에, 접근 순서가 중요하며,
컴파일러가 임의로 순서를 바꾸면 잘못된 동작이 발생할 수 있습니다.


💻 실습 예제: IAR에서 volatile 경고 해결

🎯 시나리오

  • 2개의 volatile 변수: tick_ms, button_count
  • 주기적으로 이 값을 출력하는 코드 작성
  • volatile 접근 순서 문제를 해결하는 방식 적용

⚠️ 문제 발생 코드 (비권장 예제)

#include <stdio.h>

volatile int tick_ms = 0;
volatile int button_count = 0;

void show_status() {
    // ⚠️ IAR에서는 이 코드에서 평가 순서에 대한 경고가 발생함
    printf("tick = %d, button = %d\n", tick_ms, button_count);
}
 

IAR에서는 아래와 같은 경고 발생:

Warning[Pa080]: undefined behavior : the order of volatile accesses is undefined in this statement

✅ 해결 코드 (권장 예제)

#include <stdio.h>

volatile int tick_ms = 0;
volatile int button_count = 0;

void show_status() {
    // 🟢 volatile 변수의 값을 안전하게 임시 변수에 저장
    int t = tick_ms;
    int b = button_count;

    // 🔒 이제 순서와 상관없이 안전하게 출력 가능
    printf("tick = %d, button = %d\n", t, b);
}

🧪 테스트 코드 (메인 함수 예시)

int main(void) {
    // 초기값 설정 (실제로는 인터럽트나 타이머로 갱신될 수 있음)
    tick_ms = 123;
    button_count = 7;

    // 상태 출력
    show_status();

    return 0;
}

📎 실제 프로젝트에서의 활용 팁

  • volatile 변수는 센서 읽기, 하드웨어 레지스터, 인터럽트와 관련된 데이터에 주로 사용됩니다.
  • UI에 표시하거나 로그로 출력할 때는 값을 안정적으로 복사해서 사용하는 습관이 중요합니다.
  • 특히 FreeRTOS, CMSIS 같은 실시간 시스템에서는 volatile 변수의 접근을 더욱 신중히 다뤄야 합니다.

✍️ 정리

항목 설명
문제 volatile 변수들을 하나의 printf 계열 함수에 동시에 전달할 때 평가 순서 불명확
원인 C 언어는 함수 인자의 평가 순서를 정의하지 않음
해결 volatile 값을 지역 변수에 저장한 후 사용
효과 정의되지 않은 동작 방지 + 경고 제거 + 코드 안정성 향상
 
반응형