UBSan과 TSan
정의되지 않은 동작과 경쟁 상태 찾기
UBSan과 TSan은(는) CoddyKit의 무료 C++ Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 C++ Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. C++ Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
두 가지 새니타이저 더 알아보기
ASan 외에도 서로 다른 종류의 버그를 대상으로 하는 새니타이저가 두 가지 더 있습니다.
- UBSan: 정의되지 않은 동작(오버플로, 잘못된 시프트, 널 포인터 역참조)
- TSan: 다중 스레드 코드의 데이터 경합
UBSan 활성화
UndefinedBehaviorSanitizer는 -fsanitize=undefined로 활성화합니다. ASan과 함께 사용할 수도 있습니다.
g++ -fsanitize=undefined -g main.cpp -o app
./app부호 있는 정수 오버플로
C++에서 부호 있는 정수의 오버플로는 정의되지 않은 동작입니다. UBSan은 정확한 줄에서 이를 보고합니다.
#include <climits>
#include <iostream>
int main() {
int x = INT_MAX;
int y = x + 1; // signed overflow: UB
std::cout << y << "\n";
return 0;
}UBSan이 찾는 다른 UB
UBSan은 미묘한 오류를 많이 표시합니다.
- 범위를 벗어난 시프트(32비트 정수에서
x << 40) - 널 포인터 역참조
- 정렬되지 않은 접근
- 유효하지 않은 열거형 또는 불리언 값
UBSan에서 실행 중단하기
기본적으로 UBSan은 오류를 출력하고 계속 실행합니다. -fno-sanitize-recover=undefined를 추가하면 첫 번째 오류에서 중단하므로 CI에 더 적합합니다.
g++ -fsanitize=undefined -fno-sanitize-recover=undefined -g main.cpp -o appTSan 활성화
ThreadSanitizer는 -fsanitize=thread로 활성화합니다. TSan은 데이터 경합을 탐지합니다. 즉, 두 스레드가 동기화 없이 같은 메모리에 접근하고 그중 하나 이상이 쓰기 작업을 수행하는 경우입니다.
g++ -fsanitize=thread -g main.cpp -o app -pthread
./app데이터 경합 예시
두 스레드가 잠금 없이 공유 카운터를 증가시킵니다. TSan은 경합하는 접근과 각 접근의 호출 스택을 보고합니다.
#include <thread>
#include <iostream>
int counter = 0;
void work() { for (int i = 0; i < 1000; ++i) ++counter; }
int main() {
std::thread t1(work), t2(work);
t1.join();
t2.join();
std::cout << counter << "\n";
return 0;
}경합 해결하기
뮤텍스로 공유 데이터를 보호하거나 std::atomic을 사용하세요. 수정한 후에는 TSan이 경합을 보고하지 않습니다.
#include <thread>
#include <atomic>
#include <iostream>
std::atomic<int> counter{0};
void work() { for (int i = 0; i < 1000; ++i) ++counter; }
int main() {
std::thread t1(work), t2(work);
t1.join();
t2.join();
std::cout << counter << "\n";
return 0;
}TSan과 ASan의 호환성
TSan은 ASan과 같은 빌드에서 함께 사용할 수 없습니다(서로 충돌합니다). 별도의 빌드 구성을 사용하세요. 하나는 ASan+UBSan용으로, 다른 하나는 TSan용으로 구성합니다.
새니타이저 빌드 구성표
실용적인 CI 설정에서는 두 가지 새니타이저 빌드로 테스트 모음을 실행합니다.
- 빌드 A:
-fsanitize=address,undefined - 빌드 B:
-fsanitize=thread
이렇게 하면 메모리, UB, 동시성 버그를 다룰 수 있습니다.
비용과 한계
TSan은 프로그램을 5~15배 느리게 하고 훨씬 더 많은 메모리를 사용할 수 있습니다. 모든 새니타이저와 마찬가지로 실행된 코드 경로에서만 버그를 찾으므로, 좋은 다중 스레드 테스트가 중요합니다.
빠른 확인
TSan이 무엇을 탐지하는지 떠올려 보세요.
복습
UBSan과 TSan을 배웠습니다.
- UBSan(
-fsanitize=undefined)은 오버플로, 잘못된 시프트, 널 포인터 역참조를 찾습니다 -fno-sanitize-recover를 사용하여 첫 번째 UB에서 중단합니다- TSan(
-fsanitize=thread)은 데이터 경합을 찾으며, 뮤텍스나 원자 연산으로 해결합니다 - TSan과 ASan은 별도의 빌드가 필요합니다
자주 묻는 질문
“UBSan과 TSan” 강의는 무료인가요?
네 — “UBSan과 TSan” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 C++ Academy 강의 전체를 잠금 해제할 수 있습니다. C++ Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“UBSan과 TSan”에서 뭘 배우나요?
정의되지 않은 동작과 경쟁 상태 찾기 브라우저에서 직접 실행하는 실습 코드로 C++ Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
C++ Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 C++ Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.
“UBSan과 TSan” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 C++ Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 C++ Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- gdb와 lldb 사용하기
- AddressSanitizer
- UBSan과 TSan
- Valgrind 기초