2 ポイント 投稿者 GN⁺ 2025-09-24 | 2件のコメント | WhatsAppで共有
  • Go言語がValgrindサポートを正式に追加
  • この変更により、メモリエラー検出デバッグの能力が強化
  • 開発者はメモリリークや不正アクセスをより簡単に検出可能
  • Valgrindとの互換性向上により、移植や保守作業を効率的に進められるように
  • さまざまなプラットフォームでGoコードの安定性を評価しやすくなる

GoへのValgrindサポート導入の重要性

  • GoにValgrindサポートが追加され、開発者がメモリエラー検出ツールを公式に活用できるようになった
  • この変更により、GoコードでUse-after-free、メモリリーク、不正なメモリアクセスのような問題を確認できるようになる
  • Valgrindは多くの言語でメモリ問題の検出に広く使われており、Goコミュニティにとっては信頼性と堅牢性を強化する重要な変化となる
  • 追加された機能によって、複数のプラットフォーム上でGoプログラムに対するデバッグ、品質検証、安定性評価などの作業が容易になる
  • 今回のアップデートの主な意義は、Goランタイム層にValgrind向けの計測コードが組み込まれた点にある

Valgrindとは?

  • Valgrindはメモリエラー検出、スレッドエラー、メモリリークなどを検査するオープンソースの開発ツール
  • C、C++などのシステムプログラミング言語で広く利用されており、メモリ管理の問題に対する正確な検出を提供する

今回の機能追加の要約

  • 今回の変更による**コード計測(instrumentation)**は、Goランタイムで動的に割り当てられたメモリに関するイベントをValgrindが正確に追跡できるようにする機能
  • 開発者はGoプログラムをValgrindで実行することで、潜在的なメモリ問題や不正なポインタアクセスなどを効果的に診断できるようになる
  • 結果として、Goベースのインフラやサービスにおいて高品質なコード維持と問題の未然防止というメリットがある

変化の期待効果

  • Goプロジェクトの現場でメモリエラー検出コード品質改善のプロセスがより精密になる見込み
  • さまざまなプラットフォームに配布されるGoコードの互換性と信頼性の確保が容易になると期待される

2件のコメント

 
taptaps 2025-09-25

Go言語の投稿を見ると、コメント欄にはいつも
「Rustはそんなことないのに」「Rustならその必要はないのに」っていう意見が必ずある気がしますね(笑)

 
GN⁺ 2025-09-24
Hacker Newsの意見
  • 私はこのCLの作成者で、今回の改善ではメモリ初期化追跡機能を、暗号コードが一定時間内で動作しているかを調べるための悪用、つまり定数時間性テストに使おうとしています。これは約15年前にaglが提案し、BoringSSLで行われていたものと似た方式です。関連リンク。この性質は本当にテストが難しいためです。今後もGoでValgrindの利用を有効化しつつ、ランタイムのメモリ処理を適切に追跡できるかを探るなど、いろいろと興味深い効果を期待しています。ただし、このサポートはまだ実験段階であることを強調しておきます。すべての構成でうまく動くと100%確信しているわけではなく、分かりにくい警告がさらに増える可能性もあります
    • コミュニティが開発を手伝える部分があるのか気になります
    • 本当にすばらしい機能だと思います。これによってGoのほかの問題も一緒に見つかるとよいですね。ただ、わざわざ複雑な追跡をしなくても、暗号化関数にさまざまな入力値を与えて実行時間を直接測り、すべて同じなら定数時間性を確認できるのではないかとも思いました。たとえばGarbage CollectionやOSノイズがある状況でも、複数の入力を入れて時間を測り、epsilonの誤差内に収まれば十分かもしれません。また、一部のCPUには条件分岐カウンタがあり、rr debuggerがこれを使っています。この値で復号前後の分岐回数を比較する方法もあります(aglの記事で、分岐が同一でなければ定数時間にならないという主張と関係しています)。さらに、最初の10回の復号の最大時間に少し余裕を足し、その後の復号ごとにタイムパディングを入れて(noopを実行するなど)時間を強制的にそろえる方式も可能でしょう。上限を超えた場合にプログラムをクラッシュさせる assert を入れることも考えられます。ただ、OSによるスケジュール外しなどでタイミングがずれると、この方法は難しくなります
  • Valgrindヘッダをツリーに追加してcgoを使い、各種Valgrindクライアントリクエスト用マクロを呼ぶ方法ではなく、アセンブリ関数1つで必要な命令を直接発行してクライアントリクエストをトリガーする方式を選んだのはとても良いと思います。こうしたアプローチこそ、ブートストラップツールチェーンでは望ましいものです。最小限のビルディングブロックだけを作り、残りはすべて言語レベルで処理するという考え方です
    • もしこの方法を選ばず、従来方式や別の代替案も避けるとしたら、Goのようにプロセスを単純化しつつ、ほぼ同等の性能を保つにはどうすべきだったのか気になります。こうした点は今後も解かなければならない課題だと思います
  • rscが今も活発に貢献しているのを見るのはうれしいです。特にコミットメッセージにコメントまで添えているのが印象的です。年を取るほどコミットメッセージの重要性を強く感じるようになります。valgrind追加 のように単純に残しても、あとでアーカイブするときにはあまり役に立ちません
    • rscは本当にロックスター級の開発者です。今はIssueやPR管理にAIを試すなど新しい試みも多くしていて、かなりの成果を上げるのではと期待しています
  • この機能は、すべてのパッケージに対してテストが適用されているときにだけ効果があります。そうでないと、無関係な警告に埋もれてしまいます。こうした点のせいでPythonコードではValgrindを使いにくいです
    • その話が正しいなら、CやC++にも同じことが当てはまるはずです。私の場合はPython + Boost C++のハイブリッドプログラムでValgrindを使いましたが、suppressionsファイルを1時間ほど調整したら問題なく使えるようになりました
    • 情報が多すぎるときに整理して要約するには、ローカルLLMが役立ちそうです。だからこそ、Valgrindのような batteries included なツールチェーンの役割はとても重要です
    • Go環境で「すべてのパッケージがテストされる」とはどういう意味なのか気になります
  • Valgrindは隠れた超能力です。私が書くソフトウェアの大半では、make check でテストケースを回し、make check-valgrind で同じテストをValgrind環境でもう一度実行します。後者は開発者PCでだけ使います。こうするとメモリリークや微妙なバグがよく見つかります
    • 部分的には同意しますが、マルチスレッド(Goが多用する部分)に入るとValgrindの抽象化レイヤーはあまりうまく機能しません。最後にC++コードでかなり深く試したときの基準ですが、独自スケジューラを使うため、実際の状況での並行性やrace conditionの問題はValgrindではあまり表に出ません。そして一般に性能低下もかなり大きいです。それでも何度も大いに助けられたのは事実で、今も存在してくれてありがたいです
  • 今回のサポートは本当にクールです。これでいくつかのバグがさらに見つかりそうです。気になるのは、なぜValgrindを選んだのかという点です。Clang AddressSanitizer(asan)やMemorySanitizer(msan)のほうが、より多くの種類のエラー(たとえばuse-after-return)を見つけられ、速度もずっと速いと思います
    • Goはclang/llvmを使っていないので、そうしたツールは適用できません
    • Goにはすでに独自のmsan/asanサポートが数年前から存在します
    • Valgrindはずっと高速で、実行中のプログラムにもアタッチして使えます
    • Valgrindにはメモリトラッキング、メモリプロファイリングなど多様な機能もあるので、性能追跡の観点でも非常に優れています
  • とても印象的です。Goの大きな問題の1つは、プロファイリングと、頻繁に起きるメモリリーク/メモリプレッシャーだと思っています。現時点でこの問題を解決する代替ツールは特に知りません
    • もっと詳しく聞きたいです。具体的にどんなプロファイリングの問題に直面していますか。inuseメモリプロファイルがメモリリーク追跡に十分でないなら(gorefsを使ったか気になります)、どの種のメモリプレッシャーが問題なのか教えてもらえると助かります。gorefレポ。参考までに、Datadogではcontinuous profilingに取り組んでおり、Goランタイムのプロファイリングにも継続的に貢献しています
    • GCがある言語で「持続的なメモリリーク」がどう発生するのか気になります
    • 理想を言えば、ほかの言語のようにスタックに何を置くかを明示的に制御できるようにすべきだったと思います(escape analysisだけに頼るのではなく)。現状では -gcflags -m=3 オプションや、VSCode Goプラグインの ui.codelensesui.diagnostic.annotations といった設定類で調整しなければならず、不便です
    • 「持続的なメモリリーク/メモリプレッシャー」に関しては、Goではgoroutineを作ったら確実なクリーンアップ方法が分かっていない限り作るべきではありません
    • pprofもかなりよく機能しているほうですが、さらにどんな機能が欲しいのか気になります
  • 今回の試みは悪くなさそうです。クライアントリクエストの仕組みがもし変わればリスク要因にはなりますが、ヘッダはほとんど変更されません(特に新しいプラットフォーム追加時)。Goはamd64とarm64しか扱わないので、問題も少ないです。今回の改善の本当の利点は、メモリリーク防止というより、未初期化メモリを正確に判定できることにあります。メモリが再利用される際に「ポイズニング」(意図的に使用不可にすること)処理がないと解析が難しいからです。この機能はcachegrindやcallgrindを除くほかのツールにもかなり有用です
  • 今回の改善は利益というより、Goエコシステムにとってはやや失敗に近く感じます。私はValgrindが大好きで、C開発者だった頃はよく使っていました。しかしGoがわざわざValgrindを必要とするという事実そのものが、言語やエコシステムに何か不十分な点があるように思えます。Rustを約6年間使ってきましたが、Valgrindが必要だと感じたことは一度もありません(チームメイトが一度使ったのを除けば)。これがたぶんcgoのせいだとは分かっていても、どこか退歩したような感覚は否めません
    • なぜGo関連の上位コメントにはいつもRustに言及して皮肉る内容が入ってくるのか、理解しづらいです。だんだん防御的で、しかも優越感まで混じっているように感じます
    • 今回の機能は、正しいメモリ追跡そのものよりも、定数時間コードのテスト用途で使う事例が主目的です。関連説明 もまだ少し残っています
    • RustでもValgrindをほんの少し使った経験があります。頻繁には必要ありませんが、必要性があるのは確かです。Rustは非常に幅広い環境で使われる言語です。高レベルな関数型コードから、低レベルのCライクなマイコン向けコードまであり、unsafe をまったく使わない場面もあれば必須の場面もあります。FFIでCを使うのも一般的なので、いつか必要になることはあります。以前、nginx向けのRustモジュールを作ったとき(公式/非公式のバインディングがなかった頃)、ミスが多くてvalgrindに助けられたことがありました
    • どれだけ unsafe なコードを書くか、unsafe crateやC/C++ライブラリをどれだけつなぐかによって使用頻度は変わります。Java、.NET、Nodeでも外部依存のせいで必要になる場合があります