C中main之前调用一些函数

发布于 2024-10-15 18:33:45 字数 1044 浏览 3 评论 0原文

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

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

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

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

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

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

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


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

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

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

I'd like to do some stuffs before main function. I have multiple source files. In each file, there is some work that needs to be done before main. It was no problem in C++, but problematic with C.

In C++, this can be done by two ways:

  1. Exploiting a constructor of a global class/struct.
  2. Calling a function to a global variable

For example, static const int __register_dummy_ = __AddRegisterMetaInfo(...);

However, in C, either ways is impossible. Obviously, there is no constructor. So, the first option is inherently impossible.

I thought that the second option would be possible, but not compiled in C (I tested only with Visual C++. It gives C2099.). C only allows a constant to a non-automatic variable.

Is there any way to call some functions before main?


EDIT: It seems that many people just got misunderstand what I really wanted to do. Sorry for writing this question in a simplified way.

What I needed to do is implementing a sort of C++ runtime class information feature, just like MFC's approach. In this approach, I need to get some information from all source code. For example, say each source file has a definition of a class, and I'd like to see all information (e.g., class names and the parent class). The easiest way is placing a static constructor in each file, and each constructor accesses a global data structure and register its information. But, I also wanted to find a way to implement a similar thing in C. So, simply calling a pre_main_job in main can't be an answer to me.

Note that this abuse of static constructor also can be found in LLVM compiler suite. Each optimization/analysis feature is implemented as a pass. All these passes are registered via a static constructor.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

从此见与不见 2024-10-22 18:33:45

对于许多特定于编译器的解决方案,您可以查看 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()

For a number of compiler specific solutions you can take a look at the fips_premain.c file from the OpenSSL distribution (you can view it online in a bunch of places, here for instance).

The MSVC specific part looks something like (FINGERPRINT_premain being the function to be executed before 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()
早茶月光 2024-10-22 18:33:45

您也许可以使用编译器特定的扩展来实现此目的,例如。 gcc 允许您使用 构造函数 函数属性(以及匹配的析构函数属性)使代码在main之前和main之后运行(或exit )

You might be able to use compiler specific extensions to achieve this, eg. gcc allows you to use the constructor function attribute (and the matching destructor attribute) to cause code to be run before main and after main (or exit)

逆光下的微笑 2024-10-22 18:33:45

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

我听说过一个更好的想法 - 第一,它甚至是可移植的并且行为可预测。在 main 函数的开头“在 main 之前”执行您想要执行的操作(或者调用一个在 main 的开头执行您想要执行的操作的函数) )。

如果您控制代码,那么(真的!)不需要像您提议(或介绍)那样脆弱且通常难以维护的黑客攻击。

(I know, this isn't a direct answer to the original question; it is, however, an answer for someone who's looking for a way to execute code before the contents of main)

I've heard of a better idea - one, that's even portable and predictable in behavior. Do the stuff you want to do "before main" in the beginning of the main function (or call a function which does what you want in the beginning of main).

If you control the code, there's (really!) no need for fragile and often unmaintainable hacks like the ones you have proposed (or introduced).

感情洁癖 2024-10-22 18:33:45

假设您没有将 C++ 与 C 混合在一起...(因为这样您可以在 C++ 类上执行静态构造函数,这可能就是您所要求的!)

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

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

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

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

gcc app.c -Dmain=not_really_main

然后链接到真正的 main() 中以调用 not_really_main()


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

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".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文