6

main関数の前にいくつかのことをしたいのですが。複数のソースファイルがあります。各ファイルには、前に実行する必要のある作業がいくつかありますmain。C ++では問題ありませんでしたが、Cでは問題がありました。

C ++では、これは2つの方法で実行できます。

  1. グローバルクラス/構造体のコンストラクターを利用します。
  2. グローバル変数への関数の呼び出し

例えば、static const int __register_dummy_ = __AddRegisterMetaInfo(...);

ただし、Cではどちらの方法も不可能です。明らかに、コンストラクターはありません。したがって、最初のオプションは本質的に不可能です。

2番目のオプションは可能だと思いましたが、Cではコンパイルされませんでした(Visual C ++でのみテストしました。C2099が提供されます)。Cは、定数から非自動変数のみを許可します。

mainの前にいくつかの関数を呼び出す方法はありますか?


編集:多くの人が私が本当にやりたいことを誤解しているようです。この質問を簡単な方法で書いて申し訳ありません。

私がする必要があるのは、MFCのアプローチと同じように、一種のC++ランタイムクラス情報機能を実装することです。このアプローチでは、すべてのソースコードからいくつかの情報を取得する必要があります。たとえば、各ソースファイルにクラスの定義があり、すべての情報(たとえば、クラス名と親クラス)を表示したいとします。最も簡単な方法は、静的コンストラクターを各ファイルに配置することです。各コンストラクターは、グローバルデータ構造にアクセスし、その情報を登録します。しかし、私はCで同様のことを実装する方法も見つけたかったのです。したがって、単にpre_main_jobinを呼び出すだけmainでは答えにはなりません。

この静的コンストラクターの乱用は、LLVMコンパイラースイートでも見られることに注意してください。各最適化/分析機能はパスとして実装されます。これらのパスはすべて、静的コンストラクターを介して登録されます。

4

4 に答える 4

11

コンパイラ固有のソリューションの数については、OpenSSLディストリビューションのfips_premain.cファイルを確認できます(たとえば、ここではさまざまな場所でオンラインで表示できます)。

MSVC固有の部分は次のようになります(FINGERPRINT_premain前に実行される関数ですmain):

# ifdef _WINDLL
  __declspec(dllexport) /* this is essentially cosmetics... */
# endif
  void FINGERPRINT_premain(void);
  static int premain_wrapper(void) { FINGERPRINT_premain(); return 0; }
# ifdef _WIN64
# pragma section(".CRT$XCU",read)
  __declspec(allocate(".CRT$XCU"))
# else
# pragma data_seg(".CRT$XCU")
# endif
  static int (*p)(void) = premain_wrapper;
  /* This results in pointer to premain to appear in .CRT segment,
   * which is traversed by Visual C run-time initialization code.
   * This applies to both Win32 and [all flavors of] Win64. */
# pragma data_seg()
于 2011-02-02T23:22:26.837 に答える
5

これを実現するために、コンパイラ固有の拡張機能を使用できる場合があります。gccを使用すると、constructor関数属性(および一致するdestructor属性)を使用して、コードを前後(または)で実行mainできmainますexit

于 2011-02-02T23:08:00.763 に答える
3

C++をCと混合していないと仮定します...(C ++クラスで静的コンストラクターを実行できるためです。これはおそらくあなたが求めていることです!)

Crt0main()の前に伝統的に呼び出されるプラットフォーム固有のランタイムセットアップです。あなたはそれを上書きすることができますが、それはかなり深いです。

一部の組み込みプラットフォームは、_pre_main()および_post_main()一種のプロシージャを提供します。しかし、それは非標準だと思います。

本当に、あなたの主なエントリポイントは、まあ、main()です!

Makefileを制御している場合は、mainを他の何かに強制することができます。

gcc app.c -Dmain=not_really_main

そして、実際にリンクしてmain()を呼び出しますnot_really_main()


編集:もう1つのアプローチ:gccリンカーには、最初に実行されるENTRYという変数(通常はcrt0)があります。繰り返しになりますが、これはかなり重いものであり、プラットフォームをかなり深く理解してそれを実行することができますが、「メインを破壊する」ことができるもう1つの場所です。

于 2011-02-02T23:10:47.073 に答える
3

(これは元の質問に対する直接の答えではありませんが、内容の前にコードを実行する方法を探している人にとっては答えですmain

私はより良いアイデアを聞いたことがあります-それは移植性があり、動作が予測可能です。main関数の先頭で「前に」実行したいことを実行しmainます(または、関数の先頭で実行したいことを実行する関数を呼び出しますmain)。

コードを制御する場合、提案(または導入)したような壊れやすく、多くの場合保守不可能なハッキングは(本当に!)必要ありません。

于 2011-02-02T23:39:14.023 に答える