0

このことを理解していません:私はcでプログラムを取得し、それにいくつかのセカンドパーティの静的ライブラリをリンクしています(私が知っている限り、このライブラリはdllのラッパーにもなる可能性があります)-それは私のプログラムを「暗黙的に」 (私のコードでそれを明示的に呼び出さないことを意味します) それらのライブラリからいくつかの初期化コードを実行します (それは私の main() ルーチンの前に実行されますか? - または実行できませんか?)

私はここでcコードについて質問しています(最終的にはc++機能を持たないが、c++コンパイラによってc++モードでコンパイルされたcコードについて-リンクされた静的ライブラリは任意の言語で記述できます)

答えの tnx

4

2 に答える 2

1

あらゆる種類のリンクされたライブラリは、c または c++ のコードから明示的に呼び出されない限り、初期化コードを実行できません。

于 2013-08-14T14:55:24.243 に答える
1

プラットフォームによって異なります。

GCC を使用している場合は、関数を で宣言できます__attribute__((constructor))。この関数は、動的ライブラリからでもメインの前に呼び出されます

__attribute__((constructor))
void my_init()
{
    /* do stuff; */
}

詳細については、 GCC のドキュメントこの SO の質問を参照してください。

それほど単純ではありませんが、VC でもそれを行う方法がいくつかあります。(このSOの質問を参照してください)

EDIT:サードパーティのライブラリにリンクすると、init関数が呼び出される場合があります。ライブラリがC言語であっても、それを検出するための移植可能で一般的な方法はありません。また、ライブラリがメインの開始前に呼び出されることに依存する可能性があるため、おそらくそれを台無しにしたくないでしょう。

何かを呼び出すかどうかを本当に知りたい場合は、バイナリ内を調べる必要があります。ELF ファイルには、開始時に呼び出される関数への「ポインター」を含むセクションがあり、objdump ( ).init_arrayを使用してダンプできます。objdump -s -j .init_array <binary>

WindowsのPEファイルにも同様のセクションがあると思いますが、それらを扱ったことはありません。

EDIT2 :main()関数はコードを開始します。しかし、それが実行される前であっても、やるべきことがあります。プログラムをコンパイルすると、コンパイラはプログラムの前に実行されるコードを追加し、main()プログラムの環境 (スタック、C ライブラリなど) を初期化します。

Linux では、これは主に関数_startとによって提供されます_init。また、機能として、関数内で関数を呼び出すようにコンパイラーに指示することもできます_init

動的ライブラリには関数がありませんが、ライブラリがロードされたときに呼び出される_start関数がまだあります。_initまた、いくつかのユーザー関数への呼び出しもそこに含めることができます。

静的ライブラリの場合、リンカーがプログラムから呼び出されない関数を削除する可能性があるため、もう少し複雑になります。しかし、(ライブラリ コードから間接的にでも) 呼び出されるか、ライブラリ内のどこかで参照され、実際には呼び出されない場合は、最終的にバイナリになり、 before で呼び出されmain()ます。

とに関するいくつかの情報は_startここで見つける_initことができます。

Windows では、コンパイラとリンカーは異なりますが、同様の方法で動作するはずです。

于 2013-08-14T15:18:00.410 に答える