UBSanとTSan
未定義動作とデータ競合を見つけます
「UBSanとTSan」はCoddyKit上の無料C++ Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC++ Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C++ Academyコースには全4レッスンが含まれています。
もう2つのサニタイザー
ASan 以外にも、異なる種類のバグを対象とするサニタイザーが2つあります。
- 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 が検出するその他の未定義動作
UBSan は、見つけにくいさまざまなエラーを検出します。
- 範囲外のシフト(32ビット整数に対する
x << 40など) - ヌルポインターのデリファレンス
- アラインメントに違反したアクセス
- 無効な enum 値や bool 値
UBSan を停止させる
デフォルトでは、UBSan はメッセージを表示して実行を続けます。最初のエラーで中断するには -fno-sanitize-recover=undefined を追加します。CI ではこの設定が適しています。
g++ -fsanitize=undefined -fno-sanitize-recover=undefined -g main.cpp -o appTSan を有効にする
ThreadSanitizer は -fsanitize=thread で有効にします。同期処理なしで2つのスレッドが同じメモリーにアクセスし、そのうち少なくとも一方が書き込む場合に発生するデータ競合を検出します。
g++ -fsanitize=thread -g main.cpp -o app -pthread
./appデータ競合の例
2つのスレッドがロックなしで共有カウンターをインクリメントしています。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 構成では、テストスイートを2種類のサニタイザービルドで実行します。
- ビルド A:
-fsanitize=address,undefined - ビルド B:
-fsanitize=thread
これにより、メモリー、未定義動作、並行性に関するバグをカバーできます。
コストと制限
TSan を有効にすると、プログラムが5~15倍遅くなり、メモリー使用量も大幅に増えることがあります。すべてのサニタイザーと同様に、実行したコードパス上のバグしか検出できないため、質の高いマルチスレッドテストが重要です。
クイックチェック
TSan が検出するものを思い出してください。
まとめ
UBSan と TSan について学びました。
- UBSan(
-fsanitize=undefined)は、オーバーフロー、不正なシフト、ヌル参照を検出します -fno-sanitize-recoverで最初の未定義動作が発生した時点で中断します- TSan(
-fsanitize=thread)はデータ競合を検出し、ミューテックスや atomic で修正します - TSan と ASan には別々のビルドが必要です
よくある質問
「UBSanとTSan」レッスンは無料ですか?
はい。「UBSanとTSan」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C++ Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C++ Academyコースには全4レッスンが含まれています。
「UBSanとTSan」で何を学びますか?
未定義動作とデータ競合を見つけます ブラウザで直接実行するハンズオンコードでC++ Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
C++ Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのC++ Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「UBSanとTSan」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このC++ Academyレッスンでコードを書いて実行できますか?
はい。すべてのC++ Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- gdbとlldbの使用
- AddressSanitizer
- UBSanとTSan
- Valgrindの基礎