미정의 동작(Undefined Behavior)란?
C 언어나 C++의 규격이 결과에 대해 아무것도 요구하지 않는 동작. 부호 있는 정수의 오버플로, 배열의 범위 밖 읽기/쓰기, NULL 포인터의 참조, 해제한 영역의 사용, 음수 값의 왼쪽 시프트 등이 해당한다. 컴파일러는 올바른 프로그램에서는 미정의 동작이 일어나지 않는다고 가정하고 최적화해도 되므로, 우연히 기대대로 동작하기도 하고, 최적화 설정에 따라 판정이 사라지는 등 예상하지 못한 결과가 되기도 한다. 처리계가 정하고 문서에 적는 '처리계 정의 동작'과는 구별된다.
일본어 명칭: 未定義動作
미정의 동작(Undefined Behavior)은(는) C 언어 기초, 컴파일러 등 2개 분야의 연습 문제 10개에 나와요.
분야: C 언어 기초
대표적인 예
부호 있는 정수 연산의 넘침(INT_MAX + 1 등), 배열의 범위 밖 읽기/쓰기, 초기화하지 않은 자동 변수의 값 사용, NULL 포인터나 댕글링 포인터를 통한 읽기/쓰기, 같은 영역의 이중 해제, 정수를 0으로 나누기, 형의 폭 이상의 시프트나 음수 값의 왼쪽 시프트 등이 있습니다. 부호 없는 정수의 넘침은 미정의 동작이 아니며, 2의 거듭제곱으로 나눈 나머지로 돌아간다고 정해져 있습니다.
자주 묻는 질문
미정의 동작과 처리계 정의 동작은 무엇이 다른가요?
처리계 정의 동작은 int의 크기, char의 부호 유무, 음수 값의 오른쪽 시프트 결과처럼 처리계가 하나의 동작을 골라 그것을 문서에 적어 두는 것입니다. 미정의 동작은 규격이 아무것도 요구하지 않는 것으로, 같은 처리계에서도 상황에 따라 결과가 달라져도 상관없습니다. 이식성 있는 프로그램에서는 처리계 정의 동작에 의존하는 부분을 명시하고, 미정의 동작은 일으키지 않도록 합니다.
미정의 동작이라도 동작하고 있다면 문제없나요?
문제가 있습니다. 지금의 환경에서 우연히 기대대로 동작하더라도, 최적화 설정, 컴파일러의 버전, 주변 코드가 바뀌기만 해도 다른 결과가 되는 경우가 있습니다. 보안 측면에서도 범위 밖 쓰기 같은 미정의 동작은 공격에 악용될 우려가 있습니다.