2025/07/08 23:26 A Comprehensive Proposal Overviewing Blocks, Nested Functions, and Lambdas for C

やっほー、ロボ子!今日はC言語の関数とデータの組み合わせの歴史について話すのじゃ!

博士、こんにちは。C言語の関数とデータの組み合わせ、ですか?なんだか難しそうですね。

難しくないぞ!昔のC言語の`qsort`関数は、データを受け渡すのが大変だったらしいのじゃ。関数ポインタ引数が1つしかなくて、グローバル変数とか`_Thread_local`を使うハックが横行したみたい。

なるほど。グローバル変数を使うのは、あまり良い方法とは言えませんよね。

そうそう。そこでGCCがNested Functionsっていう拡張機能を開発したのじゃ。ローカルスコープ内で関数を定義できるようになったんだぞ!

Nested Functionsですか。それは便利そうですね。ローカルデータにアクセスできるのは大きな利点です。

じゃろ?でも、セキュリティ上の懸念があって、CVEも発行されたらしいのじゃ。Non-Executable Stacksっていうセキュリティ対策と相性が悪かったみたい。

Non-Executable Stacksですか。スタックを非実行可能にすることで、バッファオーバーフロー攻撃を防ぐんですね。

そう!Nested Functionsは、エンクロージングスコープの変数を参照するために、スタックを実行可能にする必要があったから、セキュリティ的に問題があったのじゃ。

それで、Nested Functionsの代替実装が検討されたんですね。

そうじゃ!AdaスタイルのFunction Descriptorsとか、個別に割り当てられたトランポリンを使う方法とか色々試されたけど、どれも一長一短だったみたい。

GCC 14では、ヒープベースの実装が選択されたんですね。これでExecutable Stackが不要になったと。

その通り!でも、Nested Functionsは、関数値を名前または参照によってのみ「キャプチャ」するから、非同期コードとかには向いてないのじゃ。

なるほど。それで、Apple BlocksやC++スタイルのラムダが出てきたんですね。

そうじゃ!Apple BlocksはObjective-C由来で、実行時に安全にするためにランタイムが必要なのじゃ。C++スタイルのラムダは、Executable Stackとかを使わない唯一のソリューションなのじゃ。

C++のラムダは、キャプチャを手動でアノテーションする必要があるんですね。値によるキャプチャは安全に返せるけど、名前によるキャプチャはスコープ外で使用すると未定義の動作を引き起こす可能性があると。

その通り!ラムダは、C++スタイルのデストラクタを必要とするという批判もあるけど、C APIはメモリが使用できなくなったことを通知する方法を提供する必要があるのじゃ。

標準化のために、ラムダとCapture Functionsの2つのオプションが提案されているんですね。

そう!Capture Functionsは、Nested Functionsの外観と操作性を保持するけど、式ではないからマクロとかで使いにくい。ラムダはC++と互換性があるけど、関数ポインタにクリーンに変換できないのじゃ。

Make Trampolineというのもあるんですね。ユーザーがメモリの場所を選択して、トランポリンを作成するための明示的な要求が必要だと。

そう!Executable Stackに関連するCVEもたくさんあるから、セキュリティには気をつけないといけないのじゃ!

勉強になりました。博士、ありがとうございました。

どういたしまして!最後に一つ、C言語の関数は奥が深いけど、私の知識も深いのじゃ!…って、ちょっとドヤ顔しすぎたかのじゃ?
⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。