6

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.

minjang
  • 8,860
  • 9
  • 42
  • 61
  • 10
    Is any of those functions called 'I_will_explode_if_you_call_me_from_main'? – Cat Plus Plus Feb 02 '11 at 23:05
  • 1
    Out of curiosity, why would you want to do this? – Justin Morgan Feb 02 '11 at 23:06
  • 4
    One possible work-around (or solution, depending on your perspective) is to use your C++ compiler as a better C compiler; then you can cherry-pick features like static initializers. – Marcelo Cantos Feb 02 '11 at 23:06
  • 2
    perhaps start by reading [How to execute some code before entering the main() routine in VC?](http://stackoverflow.com/q/728939/203667) or [Is there any way a C/C++ program can crash before main()?](http://stackoverflow.com/q/2518415/203667) – jschmier Feb 02 '11 at 23:07
  • An example would be C++ RTCI. A global data structure needs a list of all existing class information. This trick is very useful. – minjang Feb 02 '11 at 23:09
  • @minjang: In c you accomplish that with a step in the build process (typically a code generator). – dmckee --- ex-moderator kitten Feb 02 '11 at 23:13
  • 13
    Why not just `int main(int argc, char** argv) { DoPreMainStuff(); return ActualMain(argc, argv); }` – Anon. Feb 02 '11 at 23:14
  • @PiotrLegnica I bet they're called `call_this_and_PiotrLegnica_will_explode_RIGHT_NOW()`. – Mateen Ulhaq Feb 02 '11 at 23:33
  • I removed the C++ tag, as the question specifically relates to C and only mentions C++ in a very tangental fashion. – Puppy Feb 02 '11 at 23:41
  • You shouldn't be doing this. Either remove the global variables from your program/library entirely, or initialize them with their correct initial values at compile-time so you don't have to do so at runtime. – R.. GitHub STOP HELPING ICE Feb 03 '11 at 00:18
  • 2
    Abusing C++ like that will get you hurt. There is no need to do stuff before main. Do the initialization of globals in main() then call doWork() and make this the entry point to you code. – Martin York Feb 03 '11 at 01:20
  • @Martin: MFC/LLVM do use this C++ trick to register per-source information. – minjang Feb 03 '11 at 03:59
  • In light of the edit I will reiterate: if you have to do this in c, you either implement a virtual machine that supports it and write your program against that, or you use a code generator that extracts the needed info from the source code and writes some more source code for you (with a little luck, you can keep that to headers). But usually if you are trying to make c so that you're approaching the problem wrong. – dmckee --- ex-moderator kitten Feb 04 '11 at 05:30

4 Answers4

11

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()
Eugen Constantin Dinca
  • 8,994
  • 2
  • 34
  • 51
5

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)

Hasturkun
  • 35,395
  • 6
  • 71
  • 104
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".

david van brink
  • 3,604
  • 1
  • 22
  • 17
3

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

eq-
  • 9,986
  • 36
  • 38