コンパイラがグローバルシンボルと静的シンボルを削除することに関してC++標準が言っていることへのリンクを持っている人はいますか?グローバルシンボルが参照されていない場合、コンパイラがグローバルシンボルを削除するという保証はないと思いました。私の同僚は、グローバルシンボルがメインの翻訳ユニットに含まれている場合、それらのシンボルが参照されていなくても削除されないと主張しています。
3 に答える
興味深いことに、C ++ 2003標準でこれについて見つけることができるのは、これだけです。
3.7.1静的保存期間[basic.stc.static]
動的ストレージ期間もローカルでもないすべてのオブジェクトには、静的ストレージ期間があります。これらのオブジェクトの保存は、プログラムの期間中(3.6.2、3.6.3)持続するものとします。
静的保存期間のオブジェクトに初期化または副作用のあるデストラクタがある場合、12.8で指定されているようにクラスオブジェクトまたはそのコピーを削除できる場合を除いて、未使用のように見えても削除してはなりません。
これは、初期化と破棄に副作用がなく、それ以外の場合は使用されていない場合に、標準で静的ストレージ内のアイテムの削除が許可されていることを意味します。
もっと直接的な許可があれば、私はそれを見ませんでした(しかし、おそらく他の誰かがそうするでしょう)。
ただし、リンカに最終画像内の未使用のオブジェクトを削除させることは、非常に一般的な最適化であることに注意してください。
あなたはリンクについて質問しています。C++ 標準では、リンクは変換の最終段階として行われるべきだと書かれていますが、それがどのように行われるべきかについては何も述べていません。たとえば、関数参照が解決されるとは言いますが、名前で解決する必要はなく、解決後に参照がどうなるかは述べていません。
コンパイラがオブジェクト コードに含めるシンボルと、リンカーが削除するシンボルと削除しないシンボルを判断するには、使用しているコンパイラとリンカーのドキュメントをそれぞれ参照する必要があります。
これは私が信じている方法です(これについては、以前のコメントスレッドでのスタックオーバーフローで長い議論がありました):
- 名前空間スコープを持つオブジェクト (静的ストレージ期間を持つオブジェクト) の初期化またはデストラクタに副作用がない場合、変換単位で関数またはオブジェクトが使用されていない場合、オブジェクトを最適化できます。
- 初期化または破棄が副作用を引き起こすオブジェクトの場合、オブジェクトまたはその翻訳単位の関数が使用されていなくても、コンパイラはその変数を最適化しない場合があります。
いずれにせよ、コンパイラはその使用が行われる前にオブジェクトを初期化する必要がありますが、必ずしもメインの前ではありません。私がテストを行ったのは、stackoverflow の誰かが、そのような用途がない場合、gcc は副作用のあるオブジェクトの初期化を効果的に最適化すると言ったからです。私は今それをテストしましたが、gcc がそうしないのを見てきました。さらに、私は標準を理解しているので、とにかくそうすることは許可されていません。
初期化したいオブジェクトの翻訳単位のオブジェクトまたは関数のアドレスを取得するだけで十分です。安全のために、副作用のある初期化を持つオブジェクトであっても、常にそうするようにしてください。あなたの友人が正しいと仮定すると、 main の翻訳単位は常に使用さmain
れていると見なされるため、その条件はすぐに満たされます。規則は、および(使用の定義)、(副作用の定義) にあります。3.6.2p3
3.7.1p2
3.2p2
1.9p7