【问题标题】:Calling some functions before main in C在 C 中的 main 之前调用一些函数
【发布时间】:2011-06-20 08:08:54
【问题描述】:

我想在main 函数之前做一些事情。我有多个源文件。在每个文件中,都有一些工作需要在main 之前完成。在 C++ 中没有问题,但在 C 中存在问题。

在 C++ 中,这可以通过两种方式完成:

  1. 利用全局类/结构的构造函数。
  2. 对全局变量调用函数

例如,static const int __register_dummy_ = __AddRegisterMetaInfo(...);

但是,在 C 中,任何一种方式都是不可能的。显然,没有构造函数。所以,第一种选择本质上是不可能的。

我认为第二个选项是可能的,但没有用 C 编译(我只用 Visual C++ 进行了测试。它给出了C2099.)。 C 只允许将常量转换为非自动变量。

有什么办法可以在main之前调用一些函数吗?


编辑:似乎很多人误解了我真正想做的事情。很抱歉以简化的方式写了这个问题。

我需要做的是实现一种 C++ 运行时类信息功能,就像MFC's approach。在这种方法中,我需要从所有源代码中获取一些信息。例如,假设每个源文件都有一个类的定义,我想查看所有信息(例如,类名和父类)。最简单的方法是在每个文件中放置一个静态构造函数,每个构造函数访问一个全局数据结构并注册其信息。但是,我也想找到一种方法在 C 中实现类似的东西。所以,简单地在 main 中调用 pre_main_job 不能成为我的答案。

请注意,这种对静态构造函数的滥用也可以在 LLVM 编译器套件中找到。每个优化/分析功能都被实现为一次通过。所有这些通行证都是通过静态构造函数注册的。

【问题讨论】:

  • 这些函数中是否有任何称为“I_will_explode_if_you_call_me_from_main”的函数?
  • 一种可能的解决方法(或解决方案,取决于您的观点)是将您的 C++ 编译器用作更好的 C 编译器;然后你可以挑选静态初始化器等特性。
  • 为什么不只是int main(int argc, char** argv) { DoPreMainStuff(); return ActualMain(argc, argv); }
  • 像这样滥用 C++ 会让你受伤。在 main 之前不需要做任何事情。在 main() 中初始化全局变量,然后调用 doWork() 并将其作为代码的入口点。

标签: c static-variables


【解决方案1】:

对于一些特定于编译器的解决方案,您可以查看 OpenSSL 发行版中的 fips_premain.c 文件(您可以在很多地方在线查看它,例如here)。

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()

【讨论】:

    【解决方案2】:

    您也许可以使用编译器特定的扩展来实现这一点,例如。 gcc 允许您使用constructor function attribute(和匹配的destructor 属性)使代码在main 之前和main(或exit)之后运行

    【讨论】:

      【解决方案3】:

      (我知道,这不是对原始问题的直接答案;但是,对于正在寻找在main 的内容之前执行代码的方法的人来说,这是一个答案)

      我听说过一个更好的主意 - 一个,它甚至是可移植的并且行为可预测。在main 函数的开头“在main 之前”做你想做的事情(或在main 的开头调用一个你想做的函数)。

      如果您控制代码,则(真的!)不需要像您建议(或介绍)的那些脆弱且通常无法维护的黑客。

      【讨论】:

        【解决方案4】:

        假设您没有将 C++ 与您的 C... 混合使用...(因为那时您可以在您的 c++ 类上执行静态构造函数,这可能就是您要问的!)

        Crt0 是传统上在 main() 之前调用的特定于平台的运行时设置。你可以覆盖它,但这很深。

        一些嵌入式平台提供_pre_main()_post_main() 类型的procs。但我认为这是不标准的。

        真的,您的主要入口点是main()

        如果您可以控制 Makefile,则可以强制 main 为其他内容,例如

        gcc app.c -Dmain=not_really_main
        

        然后链接您的真实main() 以致电not_really_main()


        编辑:另一种方法:gcc 链接器有一个名为 ENTRY 的变量,它是执行的第一件事,通常是 crt0。同样,这是相当重量级的,您将非常深入地了解该平台以实现它,但这是您可以“颠覆主要”的另一个地方。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-08-26
          • 2012-06-09
          • 2011-07-10
          • 1970-01-01
          • 2018-03-26
          • 2010-09-16
          • 1970-01-01
          • 2020-04-07
          相关资源
          最近更新 更多