以下の内容はhttps://error-daizenn.hatenablog.com/entry/2026/02/27/212606より取得しました。


Wine上でZigのrealpathAllocがerror: Unexpectedになる原因と、壊れないパス処理の実践解

 

Wine上でZigのrealpathAllocerror: Unexpectedになる原因と、壊れないパス処理の実践解

LinuxでWindows向けにクロスコンパイルしたZigバイナリをWineで動かしたら、std.fs.cwd().realpathAlloc(...)だけがerror: Unexpectedで落ちる――この現象は「あなたのコードが間違っている」というより、realpath系APIが抱える設計上・実装上の地雷と、Wine環境の“Windowsらしさ”の差が正面衝突して起きがちです。ここでは、なぜそうなるのかを整理し、実運用で壊れにくい代替案に置き換える方法をまとめます。 Ziggit+1

何が起きているか:Linuxでは正常、WineのWindows実行だけが失敗する理由

realpathAllocは「相対パスを絶対パスへ」「./..の解決」「シンボリックリンクの解決」などを“実体に即して”行おうとします。ここがポイントで、ファイルシステムやOS APIの挙動差を強く受けます。

  • Linuxネイティブ実行:POSIX寄りの前提でうまくいく

  • Windowsターゲット + Wine:Windows API(パス正規化、ドライブ、UNC、再解析ポイント等)を介するが、Wine側の実装や環境差で“想定外”が起こりやすい

さらにZig標準ライブラリ側でも、realpath相当は昔から挙動不一致・バグ・仕様の難しさが指摘され、そもそも標準から外したい議論まであります。つまり、Wineが悪い/Zigが悪いという単純な話ではなく、「実体ベースの正規化」はクロス環境で再現性が取りにくいのが本質です。 GitHub+2GitHub+2

error: Unexpectedが出るときに“本当に困る”ポイント

error: Unexpectedは多くの場合、「本来ならもう少し具体的なエラー(FileNotFound等)に落とせるのに、標準ライブラリが予期しない枝に入った」タイプの失敗です。加えて表示の末尾に

  • Unable to dump stack trace: Unexpected

が出ることがあり、これがデバッグをさらに難しくします。標準ライブラリのスタックトレース周りも、環境(作業ディレクトリやパス解決)で崩れる報告があります。 GitHub+1

結論:realpathAllocを“使わない設計”に寄せるのが最短で堅い

最も堅い対策はシンプルで、**「絶対パス文字列を必要としない形に設計を寄せる」**ことです。Zigが推奨しがちな流儀でもあり、標準ライブラリ側の方向性とも一致します。 GitHub+1

以下、実務で効く代替案を優先度順に紹介します。


代替案1:ディレクトリハンドル(std.fs.Dir)を基準に処理する

「cwdからの相対パスを絶対化したい」動機の多くは、結局のところ**“その場所のファイルを開きたい”**だけです。ならば、パス文字列を正規化するより、基準ディレクトリを開いてそこから辿る方が堅いです。

  • const dir = try std.fs.cwd().openDir("path", .{});

  • try dir.openFile("file.txt", .{});

  • try dir.makePath("sub/dir");

この方式だと、Wineのパス正規化差分を踏みにくく、テストもしやすいです。


代替案2:“文字列としての”正規化で済ませる(実体解決しない)

もし欲しいのが「ログ表示のためにそれっぽく整えたパス」や「..を消したい」程度なら、実体(シンボリックリンク等)に触るrealpathは過剰です。

  • std.fs.path.resolve など、純粋な文字列操作で整形する

  • ただし、これは「存在確認」や「リンク解決」をしないので、用途を限定する

“実体に触れない”ので、Wineの再解析ポイントや特殊パスで死ににくいのが利点です。


代替案3:Windows専用のAPIで絶対パスが必要な場合だけ分岐する

どうしても外部ツール連携やGUI、ログ要件で「Windowsの絶対パス(C:\...)が必須」なケースはあります。その場合は、

  • WindowsではWindows API相当(例:GetFullPathNameW系)で解決

  • LinuxではPOSIX寄りで解決

  • Wineテスト時は「Windows分岐」で動くかを見る

という形で、ターゲットOSに即した実装に寄せるのが安全です。realpath一発で全部片付けようとすると、まさに今回のような差分で苦しみます。


代替案4:テスト環境を“Wine前提”から一段だけ現実に寄せる

Wineは非常に便利ですが、ファイルシステムまわりは「完全にWindowsと同じ」ではありません。再現性を上げるなら、

  • 実Windows(VMでも可)で1回は通す

  • CIにWindowsランナーを入れる

  • Wineは“動作の目安”として扱い、パス系は特に過信しない

という運用が結果的に早いです。Wine上でZigやWindows API絡みの問題が起きる報告自体もあります。 GitHub


ありがちな落とし穴チェックリスト

realpathAlloc系でハマりやすい条件を先回りで潰すと、原因切り分けが早くなります。

  • 指定した相対パスがWine実行時のcwdから見て本当に存在しているか

  • Windowsパス区切り(\)とZig内の表現(/)の混在

  • ドライブレター、UNC、特殊ディレクトリ(C:だけ等)を踏んでいないか

  • シンボリックリンク/ジャンクションの解決を要求していないか

  • 実行時にcwdが変わる設計(起動スクリプトや親プロセス都合)になっていないか


まとめ:壊れない方針は「絶対パス文字列を最終手段にする」

  • realpathAllocはクロス環境、とくにWineで不安定になりやすい

  • 目的が「ファイルを扱うこと」なら、Dir基準(ハンドル基準)に設計を寄せるのが最強

  • 表示用なら“文字列正規化”で十分なことが多い

  • どうしても必要なときだけWindows専用の方法に分岐する

この方針に切り替えるだけで、今回のerror: Unexpectedだけでなく、将来のパス周りの不具合(環境依存・再現困難)をまとめて減らせます。 GitHub+1




以上の内容はhttps://error-daizenn.hatenablog.com/entry/2026/02/27/212606より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14