Osx では、dylib リンカのインライン関数は、最初に使用された関数を使用します。したがって、たとえば、インライン関数が最初にメインの実行可能ファイルで使用され、次にロードされた dylib で使用される場合、メインの実行可能ファイルのインライン関数が使用されます。
これは、インラインがグローバル シンボルを参照しない限り、通常は問題ありません。
繰り返しますが、同じバージョンが一貫して使用されるため、通常はこれで問題ありません。
この問題は、実行可能ファイルと dylib の両方にあるグローバルを参照する 2 つのインライン関数があり、1 つの関数が実行可能ファイルで最初に使用され、別の関数が dylib で最初に使用される場合に発生します。次に、ミスマッチのペアがあります。例えば:
class MagicAlloc
{
void* Alloc() { return gAlloc.get(); }
void Free( void* v ) { gAlloc.free( v ); }
static RealAllocator gAlloc;
};
実行可能ファイルで MagicAlloc::Alloc を呼び出し、それを dylib で呼び出すとします。両方のすべての割り当てに対して、実行可能ファイルで gAlloc を使用します。次に、MagicAlloc::Free への最初の呼び出しが dylib で発生します。次に、グローバルのバイナリに割り当てられた何かを dylib から解放しようとします。
次の 2 つの解決策があります。
グローバル/静的を参照するためにインラインを使用しないでください。グローバル構造と関数定義を同じ翻訳単位 (オブジェクト ファイル) に移動します。グローバルを「静的」とマークして、TLU の外部からは見えないようにします。これで、関数はリンク ステップで静的に解決され、適切なグローバルにバインドされます。
プラグイン API を除く、実行可能ファイル内のすべてのシンボルを非表示にします。通常どおりリンクしますが、バイナリ自体をリンクする場合は、次をリンカーに渡します。
-Wl,-exported_symbols_list,export_file
export file は、エクスポートする必要があるリンク シンボルのリストです。たとえば、そのファイルには少なくとも「_main」が必要です。これで、dylib を実行すると、間違ったインラインに動的にリンクできなくなります。これは、動的シンボル テーブルにないためです。2 番目のソリューションは、悪意のあるプラグインがグローバルに簡単にアクセスできないため、より安全です。