クロススレッド・スタック・アクセスは競合状態か?

同カテゴリーの次の記事

マルチスレッド開発ガイド: 4.7 データ構造とメモリー・アクセス・パターンを最適化してデータの局所性を高める

この記事は、インテル® ソフトウェア・ネットワークに掲載されている「Is a Cross-thread Stack Access a Race Condition?」(http://software.intel.com/en-us/articles/is-a-cross-thread-stack-access-a-race-condition/) の日本語参考訳です。



インテル® Inspector XE を利用してマルチスレッド・アプリケーションの問題を解析する場合、レベル 2 (“デッドロックとデータ競合の検出”) または 3 (“デッドロックとデータ競合の特定”) を指定し、アプリケーションのスレッドのチェックを行うと、インテル® Inspector XE は “クロススレッド・スタック・アクセス” の警告を出力することがあります。この警告はやや分かりづらいため、この記事ではこの警告が検出される状態について詳しく説明します。 

cross+stack+access1.png

最初に、この警告はデータ競合を示すものではありません。クロススレッド・スタック・アクセス (CTSA) の警告は、コードで使用されているロックに関係なく、常に出力されます。すべての CTSA は、”スレッド A がスレッド B のスタックにアクセスしている” ことを示すもので、競合状態やエラーを示しているわけではありません。これはただの警告です。

CTSA は、意図しない場合に複数のスレッドがスタックを共有することがないように警告として出力されます。さらに、別のスレッドのスタックにアクセスすることは、適切に同期が行われない場合、安全ではないことも示します。

mutex はこの安全性を保証するのに十分ではありません。競合が安全であることは保障できますが、アクセス時にスタック変数がまだ “存在する” (つまり、所有者がまだ実行中でフレームがスタックからポップされていない) かは保障できません。

これは、次の例を見ると分かりやすいでしょう。

前処理:

int *p; // グローバル変数



CreateThread(..., thread #1, ...);
CreateThread(..., thread #2, ...);

スレッド #1:
{
    int q[1024]; // Thread #1 にスタックを割り当て
    p = q;
    q[0] = 1;
}

スレッド #2:
{
    *p = 2; // Thread #1 のスタックにアクセス
}

スレッド #1 とスレッド #2 が同時に実行し、スレッド #1 とスレッド #2 の間でほかの同期が行われない場合、スレッド #2 が ‘*p = 2;‘ を実行する前にスレッド #1 が ‘p = q;‘ を実行すると、インテル® Inspector XE はクロススレッド・スタック・アクセスを検出します。

この例では、スレッド #1 がローカルスタック変数 q のアドレスをグローバルポインター p に格納し、後でスレッド #2 がグローバルポインター p を逆参照してスレッド #1 のスタックにアクセスすることで、スレッド #1 の変数 q に書き込んでいます。

クロススタック・アクセスの検出

カスタム解析タイプを作成し、[Detect data races on stack accesses (スタックアクセスのデータ競合を検出する)] を有効にすることができます。カスタム解析タイプの作成の詳細は、製品ドキュメントを参照してください。カスタム解析タイプを指定したら、[Detect data races on stack accesses (スタックアクセスのデータ競合を検出する)] をオンにして、CSTA が発生している場所を特定します。

cross+stack+access2.png

注: このオプションをオンにすると、解析のオーバーヘッドが増えます。

また、[Cross-thread stack access detection (クロススレッド・スタック・アクセスの検出)][Show problems/Hide warnings (問題を表示/警告を非表示)] に設定すると、[Summary (サマリー)] タブに検出された問題を表示し、[Collection Log (収集ログ)] タブに警告を表示しないようにできます。

cross+stack+access3.png

これにより、クロススレッド・スタック・アクセスを正確に特定することができます。

編集部追加

インテル® Inspector XE は、アプリケーション実行時の問題を検出するツールです。マルチスレッド・プログラミングにおいては、共有データの競合、およびデッドロックといった新たな問題を考慮する必要があります。これらは時に再現性が低く、問題箇所の特定が難しいため、デバッグに多くの時間を要するでしょう。インテル® Inspector XE を用いると、アプリケーションを1回テスト実行するだけで、これらのような問題となり得る動作が検出され、問題の種別ごとにソースコード中の定義および記述と対応付けられた形で確認することができます。

インテル® Parallel (C++/Fortran) Studio XE には、このインテル® Inspector XE が含まれており、さらにこれらの Studio XE 製品ではインテル コンパイラーと連携して SSA (スタティック・セキュリティー解析) 機能を使用できます。高速化のみならず、デバッグをも支援するインテル® ソフトウェア開発製品を、是非ともお試しください。お問い合わせや評価版のダウンロードはエクセルソフト株式会社まで。

コンパイラーの最適化に関する詳細は、最適化に関する注意事項を参照してください。

関連記事