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


Windowsでは通るのにLinuxで落ちる原因は「型の違い」だった?Zig+SDL3+ImGui+ImPlotのundefined symbol解決ガイド

 

Windowsでは通るのにLinuxで落ちる原因は「型の違い」だった?Zig+SDL3+ImGui+ImPlotのundefined symbol解決ガイド

WindowsではSDL3+ImGui+ImPlotのC++プロジェクトが普通にビルドできるのに、Linuxだけリンク時に ld.lld: undefined symbol で落ちる――この手のトラブルは、ソースやライブラリの不整合というより「テンプレートと型サイズの差」で説明がつくケースがよくあります。
今回のエラーはまさにそれで、原因を理解すると最短で直せます。

起きていること:Linuxだけ ImPlot::PlotBars<unsigned long> が見つからない

ログの要点はこれです。

  • Linuxでリンク時に未定義参照(undefined symbol)

  • 未定義なのは void ImPlot::PlotBars<unsigned long>(...)

  • しかも「似た候補」として PlotBars<signed char> が提示され、implot_items.o に定義があると言われている

つまり「ImPlot自体はリンクできているが、unsigned long 用の PlotBars 実体がどこにも生成されていない」状態です。
C++のテンプレートは、定義がヘッダ内にあるか、あるいは .cpp側で明示的インスタンス化しているかでリンクの挙動が変わります。このエラーは後者パターンで起きやすい典型例です。

いちばん多い真因:WindowsとLinuxで unsigned long の意味が違う

ここが最大の落とし穴です。

  • Windows(多くの環境は LLP64):unsigned long32bit

  • Linux(一般的な x86_64 は LP64):unsigned long64bit

同じ unsigned long と書いても、OS/ABIが違うと別物になり得ます。
ImPlot側が「ある型の組み合わせだけ」を .cpp で明示的にインスタンス化している(または内部でサポート型が限定されている)場合、Windowsでは偶然 “32bit枠” に収まって通っても、Linuxでは “64bit型” になって未対応=未生成になり、リンクで落ちます。

今回、未定義なのが PlotBars<unsigned long> であることは、まさにこの状況を強く示唆します。

解決策A:固定幅整数に置き換える(最短・安全・おすすめ)

クロスプラットフォームで型を安定させるなら、unsigned long を捨てて uint32_t / uint64_t に寄せるのが正攻法です。
さらに、ImPlotに渡す型は「ライブラリが確実に扱える型」に寄せるのが無難です。

例:元が unsigned long* の配列なら、まず描画用に doubleint に変換するのが堅いです。

cpp
#include <cstdint> #include <vector> // 例:counts が本来 unsigned long だったもの std::vector<double> plot_values; plot_values.reserve(count); for (int i = 0; i < count; i++) { plot_values.push_back(static_cast<double>(counts[i])); } ImPlot::PlotBars("counts", plot_values.data(), count);

値が大きく double 変換が嫌なら、まずは uint32_t へ整理できないか検討してください(多くのヒストグラム・カウント用途は32bitで足ります)。

cpp
std::vector<uint32_t> v32; v32.reserve(count); for (int i = 0; i < count; i++) v32.push_back(static_cast<uint32_t>(counts[i])); // ImPlot側が uint32_t を確実に持っているかは実装次第なので、最終的に double へ寄せるのが安全

ポイントは「unsigned long をAPI境界に持ち込まない」ことです。WindowsとLinuxで意味がズレる型を使うと、今回のように“片方だけ”落ちる温床になります。

解決策B:ImPlot側で unsigned long の明示的インスタンス化を追加する(根治だが保守コストあり)

もしプロジェクト都合でどうしても unsigned long をそのまま PlotBars に渡したいなら、ImPlotの実装に合わせて unsigned long 用の実体を生成させる必要があります。

よくある構造は次のどちらかです。

  1. テンプレート定義がヘッダに無い(.cppにある)

  2. .cpp末尾で「対応型だけ」明示的インスタンス化している

この場合、implot_items.cpp などの末尾付近にある“対応型リスト”に unsigned long を足す、あるいは同様の記述を追加します(実際のマクロ名・書式はImPlotの該当ファイルに合わせてください)。

ただしこの方法は、ImPlot更新時に衝突しやすく、チーム開発では差分管理が面倒になりがちです。
長期的には解決策A(固定幅型+描画用型への変換)の方がトラブルが減ります。

解決策C:ビルドの一貫性をチェック(「本当は別物をリンクしていた」を潰す)

今回のログだと implot_items.o 自体は作られていて参照もされているので、完全な未リンクではなさそうですが、念のため次も確認すると事故を防げます。

  • ImPlot/ImGuiの全ソースが同じC++モードでコンパイルされているか(例:C++17など)

  • Linux側だけ #define が違っていないか(IMGUI_DISABLE_*IMPLOT_* 系)

  • ある翻訳単位だけ -fno-rtti -fno-exceptions など差が出ていないか

  • implot_items.cpp を別設定でビルドしていないか(Zig経由だとフラグ差が混じることがある)

ただ、今回の未定義シンボル名が “特定型のテンプレート” にピンポイントで出ているため、ビルド不整合よりも「型のズレ(unsigned long)」が主犯である可能性が高いです。

まとめ:Linuxだけ落ちるなら、まず unsigned long を疑う

  • unsigned long はWindowsとLinuxでビット幅が変わりやすい

  • テンプレート関数が「対応型だけ実体化」される構造だと、片OSだけ未定義参照が起きる

  • 最短で強い対処は「固定幅型に寄せる」「ImPlotに渡す前に double 等へ変換する」

  • どうしても必要ならImPlot側で明示的インスタンス化を追加(ただし保守コスト増)

同じコードがWindowsで動くほどややこしいのがこの問題ですが、原因はシンプルです。API境界の型を安定させれば、Linuxでも一気に通るようになります。




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

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