volatile 휘발성 변수...
오늘 로봇 공학 숙제를 하다가 처음 발견한 명령어 volatile
이런 명령어가 있는지 몰랐다.
인터넷으로 검색해보니 바로 나온다.
사전적 의미로는 '휘발성의'...
간단히 설명을 들어보니, 중간에 변수 내용이 변경될 수도 있다라는 것을 컴파일러에 알려준다는
것이다라고 되어있다.
무슨 말인지 도통 모르겠어서 좀더 예제를 찾아보았다.
쓰레드의 경우 아래와 같은 코드가 있다고 보자
[CODE type=cpp] void ThreadEntry(void* pParm){
bool* pbExit = static_cast<bool*>(pParm);
int i = 0;
while( !*pbExit) {
i++;
}
printf("i = %d\n" ,i);
}[/CODE]
bool* pbExit = static_cast<bool*>(pParm);
int i = 0;
while( !*pbExit) {
i++;
}
printf("i = %d\n" ,i);
}[/CODE]
이 코드에서 보면 매개변수로 넘어오는 pParm은 외부에서 언제든 변경될 수 있는 값이다.
아마 쓰레드의 종료를 처리하는 변수 같은데
Debug모드에서는 아무 문제없이 잘 작동이 되나 Release모드에서는 오작동을 일으키게 된다.
그 이유는 컴파일러가 코드를 최적화하기 때문이다.
위의 코드를 보면 while반복문을 도는 동안 pbExit의 변수는 사용하지를 않는다.
변수를 읽는 일만 하고, 변경을 가하는 일 따위는 하지 않기 때문에 똑똑한 컴파일러는
굳이 *pbExit의 값을 매번 비교할 필요가 없다고 생각하고 비교하는 코드를 제거해버린다.
그럼 무한루프트에 빠지게 되는 것이다.
해결 방법은 아래와 같이 해주면 된다.
[CODE type=cpp]volatile bool* pbExit = static_cast<volatile bool*>(pParm);[/CODE]
또 다른 예를 보자.
[CODE type=cpp]int i;
double j;
for (i=0;i<100;i++) {
j=sqrt(2.8)+log(3.5)+56;
// do something
}[/CODE]
double j;
for (i=0;i<100;i++) {
j=sqrt(2.8)+log(3.5)+56;
// do something
}[/CODE]
이 코드 역시 j는 항상 일정한 값만 갖게 된다. 똑똑한 컴파일러는 역시 최적화를
아래와 같이 시켜준다.
[CODE type=cpp]j=sqrt(2.8)+log(3.5)+56;
for (i=0;i<100;i++) {
// do something
}[/CODE]
for (i=0;i<100;i++) {
// do something
}[/CODE]
물론 외부에서 j의 값을 바꾸지 않는한 오류는 나지 않고 위의 코드와 완전 동일하게
수행이 될 것이다.
하지만 만약 j가 전역변수이고, 쓰레드로 동시에 공유하는 변수를 사용한다고 가정하면
예기는 달라진다. 프로그래머가 전혀 의도하지 않은 결과값을 초래할 수도 있으므로
이 점을 유의하면서 프로그램을 짜도록 하자.
출처 : 돌아이님의 블로그 글