프로그램/ATMega

IAR 컴파일러 Warning : undefined behavior: the order of volatile accesses is undefined in this statement

와이즈캣 2010. 4. 1. 19:01

얼마 전 후배의 질문이 있어 답변했다가 문득 정리해 두어야 하지 않을까 싶어 정리해 본다.


후배가 IAR 컴파일러로 컴파일 할 때 아래와 같은 워닝이 떠 제거하기 위해 검색했다고 한다.


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



관련된 소스를 대충 살펴 보면 아래와 같다.

volatile int iPinA;
volatile int iPinB;

// ......

iPinB *= iPinA;



밑출친 부분에서 워닝이 감지된다.
이는 volatile에 대한 정확한 인지가 문제이다. 이걸 설명한 댓글에 보니까 컴파일러가 좋지 않아서
그렇다는 댓글도 봤는데 그건 상용 컴파일러에 대한 인지가 더 낮아서 그렇다.

gcc 컴파일러는 여러 CPU를 지원하고 나름 우수하기도 하지만 임베디드 관련 개발자 들은 상용
컴파일러가 왜 좋은지 알고 있다. 해당 CPU에 대한 최적화가 잘되어 있고 명령어 지원이 충실하며
무엇보다 많은 컴파일 옵션을 지원한다.
실제 생성된 기계어를 비교해 보면 돈주고 산 컴파일러가 확실히 좋다.(자세한 건 생략~ ㅡ_ㅡ;)

위와 같은 상황에서 보면

iPinB *= iPinA;

를 풀어쓰면

iPinB = iPinB * iPinA;


가 된다.

컴파일러는 여기서 고민에 빠진다. 곱셈을 하기 위해선 iPinB를 읽어 오든 iPinA를 읽어 오든
하나씩 차례대로 읽어 General Register에 저장해야 한다. 그러면 하나를 읽는 중에 다른
하나의 Data는 이미 과거가 되어 버린다.
상황에 따라 이 부분이 심각하게 프로그램에 영향을 미칠 수 있다. 그럴경우 책임 소재는 어디에
있는가?? 컴파일러? 개발자??
개발자가 이 부분이 심각함에도 컴파일러에게 의존해서 모르고 지나쳐 버린다면 컴파일러가 책임을
지는가?? 물론 아니다... 따라서 상용 컴파일러인 IAR 컴파일러는 개발자에게 주의를 준다.
혹시 모르니 앞뒤를 분명히 해 달라고 말이다. 그게 저 워닝이다.
해결책은 순서를 명확하게 코드를 정리해 주면 된다.


volatile int iPinA;
volatile int iPinB;

// ......

int temp;

temp = iPinA;
iPinB = iPinB * temp;



이렇게 되면 상황상 iPinA가 먼저 적재되게 된다. 순서가 명확해 진 것이다.
이 워닝은 컴파일러가 좋고 우수할수록 더 자주 찾아 볼 수 있다.
이렇게 안해주는 컴파일러가 오히려 더 안 좋은 것이다.

이런면에서나 최근 ARM 컴파일을 할 때 마다 느끼지만 gcc는 성능이 많이 낮은 편이다.
하지만 그 넓은 활용 분야에는 정말 놀라울 뿐이다.
하지만 gcc에만 빠져 상용 컴파일러의 진정한 성능을 모른다면 개발자로서 우물안의 개구리를
벗어 나지 못한다면 안타까울 뿐이다.
이 워닝에 대한 댓글을 보고 정말 안타까워 글을 몇자 적어 봤다.

그런데도 난 gcc가 좋다...
ㅋ~ makefile의 조합이나...
그 심플함이란...
: )