Skip to main content

Axivion:C/C++/Rustコードベース全体に対応するひとつのツール

コメント
このブログは「Axivion: One Tool for Your Entire C/C++/Rust Codebase」を翻訳・一部加筆したものです。

今年5月、RustがAxivionの正式サポート言語となりました。これにより、既にAxivionユーザーが利用している静的コード解析、アーキテクチャ検証、品質モニタリングの各機能が、C、C++、C#、CUDA C++と同様にRustでも利用可能になりました。

本記事は、既存のC/C++コードベースにRustを導入しようとしているチーム向けに、Axivionの役割を解説するものです。

混在コードベース:多くのチームが直面している状況

Rustを採用するチームの多くは、RustとC/C++が何年にもわたって共存する混在コードベースを扱うことになります。

最もよく見られる構成は、新規モジュールをRustで書きつつ、システムの大部分はCやC++のまま残すというものです。そして両者はForeign Function Interface(FFI)境界を越えてやり取りする必要があります。この構成は、Rustのツールチェーンだけでは解決できない問題を生み出します。これはハイブリッドコードベースに蓄積しがちな種類の欠陥であり、まさにAxivionが対処するために作られたものです。

コードベース内のすべての言語を単一のモデルで扱う

Axivionは、エンジニアリングチームと品質チームに対し、C、C++、C#、Rust、CUDA C++にまたがるアーキテクチャ、メトリクス、コードの健全性を一つのビューで提供します。

アーキテクチャ検証、静的コード解析、品質モニタリングはすべて、モジュールがどの言語で書かれていても、システム全体の同一モデルに基づいて動作します。これまでは、開発者は言語ごとに別々のレポートをやりくりし、ツールを切り替え、手作業で結果を突き合わせながら、それでも言語の境界に潜むバグを見逃す可能性がありました。Axivionを使えば、ダッシュボードは一つだけです。Rust、C、C++それぞれの検出結果を一箇所にまとめ、言語をまたぐ問題も含め、コンテキストスイッチなしで確認できます。

以前の記事「複数開発言語ソフトウェアプロジェクトに潜む落とし穴」および「Axivionによる多言語ソフトウェアプロジェクトの解析」も併せてご覧ください。

RustとC++が接する場所で問題が起きる

RustとC/C++の間のFFI境界は、Rustの安全性保証が及ばなくなり、人為的ミスが入り込む場所です。また、1つの言語しか見ない、ファイル単位・関数単位でしか見ないツールにとっては死角にもなります。

Axivionのアーキテクチャ検証を使えば、Rustとレガシーコンポーネントがどのようにやり取りしてよいかについてルールを設定できるため、こうしたリスクの高い境界を、リリース前に可視化し、管理下に置くことができます。

FFIの実践:Clippyが見逃し、Axivionが検出する問題

シナリオ:RustからCを呼び出す

あるハードウェア制御ユニットがCの通信インターフェースを持っています。新しいRustモジュールがFFI経由でこれにバインドし、send_commandを呼び出してHWCommand構造体をデバイスへ送出します。

C側(エクスポートされるインターフェース)

// exports.h
#pragma pack(push, 1)
typedef struct {
    short id;
    int   flags;
    double value;
} HWCommand;
#pragma pack(pop)

void send_command(HWCommand cmd);

#pragma pack(push, 1)はフィールド間のパディングを除去します。この構造体はC側で14バイトになります。

Rust側(FFIバインディング)

// main.rs
#[repr(C)]         // 意図は正しいが、`packed` が欠けている
struct HwCommand {
    id:    i16,
    flags: i32,
    value: f64,
}

extern "C" {
    fn send_command(cmd: HwCommand);
}

fn main() {
    let cmd = HwCommand { id: 1, flags: 1, value: 3.14 };
    unsafe { send_command(cmd); }
}

#[repr(C)]はCと互換性のあるフィールド順序を保持しますが、ナチュラルアライメントが適用されます。つまり、idの後に2バイトのパディングが挿入され、flagsが4バイト境界に揃えられます。Rust側の構造体は16バイトになります。

実行時に起きること

デバイスは不正なデータを受信します。flagsとvalueが誤ったバイトオフセットから読み込まれます。出力は次のようになります。

Received Command - id: 1, flags: 65536, value: 0.000000

本来期待される出力は次の通りです。

Received Command - id: 1, flags: 1, value: 3.140000

Clippyに見えるもの

何も見えません。Clippyは完全にRustのコンパイル単位の内側でのみ動作します。#[repr(C)]の使用は正しく検証し、unsafeブロックもチェックし、よくあるRustのミスも検出しますが、境界の反対側にあるCヘッダーや#pragma packディレクティブについては一切把握していません。Clippyの視点では、このバインディングは問題なく見えます。

Axivionが検出するもの

Axivionは両方の言語側を同時に解析します。Rust-CheckExternSignaturesルールは、Rustのextern "C"宣言を実際にエクスポートされたCシンボルと比較し、次のように報告します。

Import signature does not match export signature Parameter type differs — size differs: 16 vs. 14

修正はたった1行です。

#[repr(C, packed)]
struct HwCommand { ... }

この問題の重要性

この種のバグ、つまりFFI境界におけるレイアウトの不一致は、どれほど徹底したツールであっても単一言語向けのツールでは検出できません。Rustコンパイラはこのバインディングを受け入れます。Cコンパイラはこのシンボルをエクスポートします。両方の言語モデルを同時に保持するツールだけが、両者の間の契約が破られていることを見抜けます。これこそが、Axivionのクロス言語解析が提供する価値です。

同じ原理は、C#のP/Invoke、PythonのctypesなどほかのFFIメカニズムにも当てはまります。個々のコンパイラはシステムの半分しか見ていませんが、Axivionはシステム全体を見ています。

Clippyはステップ1、Axivionはステップ2

Rustプロジェクトのほぼすべてが既にClippyを実行しており、それは正しい出発点です。Clippyはイディオマティックなコードを強制し、よくあるミスを検出し、あらゆるCIパイプラインに組み込まれるべきものです。

しかしClippyはファイルおよび関数レベルで動作します。システムのアーキテクチャについては何も把握しておらず、大規模なチーム全体でのコード品質の経時的な推移も示せませんし、安全性が求められる開発におけるコンプライアンスや監査の要求に応えるようには作られていません。

Axivionは、Clippyが対象としない部分を引き継ぎ、安全性が求められるプロジェクトやエンタープライズプロジェクトに必要なアーキテクチャの健全性と長期的な品質ガバナンスを追加します。

では、これは何を意味するのでしょうか?

パイプラインにはClippyを残したまま、その上にAxivionを追加してください。

新しいRustコードに古いC++の轍を踏ませない

技術的負債は、予防する分には安価ですが、後から解消しようとすると高くつきます。

Rustを採用するチームには、隣にあるC/C++システムを蝕んできたのと同じ緩やかな劣化を引き継ぐのではなく、クリーンなコードベースから始められるという、めったにない機会があります。

Axivionのデルタ解析を使えば、新たに発生した問題だけに集中できるため、レビューのたびに過去の指摘事項について議論することなく、最初のコミットからRustコードを高い基準で維持できます。

現時点では純粋なRustのみのプロジェクトはまだ珍しく、本番環境で稼働しているものはほとんどありません。規制の厳しい環境で完全にRustへ移行するとなると、認証作業をやり直すことになります。当面の間、多くのチームはC/C++/Rustが混在する状況にとどまることになりますが、Axivionはまさにそうした状況のために作られています。

コードベースのRustへの移行が進むにつれ、AIによる翻訳(トランスレーション)が行われるケースも含め、そのAI生成コードにも人間が書いたコードと同じチェックが必要になります。

 

AIワークフロー向けAxivion

AIが生成したRustコードは、同じFFIの多いコードベースに組み込まれます。コンパイルは通ります。Clippyは何も言いません。しかしAxivionのアーキテクチャモデルは、最初のコミットの時点でレイヤー違反を検出します。

Axivionは、説明の提供、修正案の提示、アーキテクチャに関するガイダンスなど、開発者の生産性を高めるAI支援の力を存分に提供します。

解析エンジン自体はAIを一切使用せず、完全に認証取得可能な状態を保っているため、認証ワークフローに単一のリスクも持ち込むことはありません。

 

現在お使いの言語構成がどのようなものであっても、また数年後にどう変化していても、1つのツールでカバーできます。

Axivion Suite、その静的コード解析機能、アーキテクチャ検証機能について詳しくはこちらをご覧ください。

 

ニュースレターにご登録ください

最新ニュース、ブログ、記事、ウェビナーなどの最新情報をお届けします

 

コメント

ブログを購読

Qt 6.11 を今すぐ試そう!

最新リリースはこちらからダウンロードできます。 www.qt.io/download

 Qt 6.11 がリリースされました!アプリケーション開発者やデバイス開発者向けに、多くの新機能と改善が追加されています。 

採用情報 

現在、さまざまなポジションで採用を行っています。募集職種はこちら をご覧ください。また、Instagram をフォローして #QtPeople の働き方もぜひチェックしてください。