6

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

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

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

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

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

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

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


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

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

请注意,这种对静态构造函数的滥用也可以在 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和之后运行mainexit

于 2011-02-02T23:08:00.763 回答
3

Assuming you are not mixing C++ in with your C... (because then you could do the static constructors on your c++ class, which is maybe what you're asking!)

Crt0 is the platform-specific runtime setup traditionally called before main(). You could override that, but that's pretty deep.

Some embedded platforms provide a _pre_main() and _post_main() kind of procs. But that's nonstandard I think.

Really, your main entry point is, well, main()!

If you're in control of the Makefile, you could force main to be something else, with something like

gcc app.c -Dmain=not_really_main

And then link in your real main() to call not_really_main().


edit: one more approach: The gcc linker has a variable called ENTRY which is the first thing executed, usually crt0. Again, this is pretty heavyweight, and you'll have understand the platform pretty deeply to pull it off, but it's another place you can "subvert main".

于 2011-02-02T23:10:47.073 回答
3

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

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

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

于 2011-02-02T23:39:14.023 回答