0

In C++ it's possible to call arbitrary functions at init time before main() has been entered, including calls to libraries that are not fully initialized yet, which can cause confusing errors. If I'm writing a library, is it possible in standard modern C++ (C++20 or so) to tell whether main() has started yet, so I can prevent the user of the library from using it before it's safe?

Considered solutions:

  • Having a library::init() function called at the beginning of main(). The library already works fine without an init(), so it seems silly to add one just to improve error reporting. If nothing else works, obviously this is the best solution.
  • Using a static initializer to determine when it's safe to use the library. It cannot be predicted what order static initializers run in, so this is not reliable.
  • Using a function-level static variable to initialize the library (essentially lazy initialization) so that initialization order doesn't matter. I already do this for some things, but this can't extend the protection to other libraries or system resources that are not usable before main().
  • Walking up the stack manually to find a frame for main(). I think not. : )
  • Disclosure: This is the second time I've posted this question. I deleted the first post because it contained too much irrelevant information that distracted readers from the actual question. – quietfanatic Dec 10 '22 at 22:48
  • 1
    Nope. C++ does not work this way. – Sam Varshavchik Dec 10 '22 at 22:56
  • Didn't think so, just wanted to make sure nobody else had any ideas. Thanks! – quietfanatic Dec 10 '22 at 22:59
  • 1
    C++23 does at least have standard stacktrace support, but hunting through it for `main` is still not portable and also wouldn't handle a different entry point name such as `WinMain`. – chris Dec 10 '22 at 23:02
  • I didn't think of that caveat, that would throw solution #4 out the window if it wasn't out several windows already. : ) – quietfanatic Dec 10 '22 at 23:04
  • You can do it yourself. `extern int main_started;` in a header. `int main_started = 0;` at global scope in your **main.cpp** file. First line of `main` is `main_started = 1;`. – Eljay Dec 10 '22 at 23:24
  • This is a library, and the library doesn't have control over `main`. – quietfanatic Dec 11 '22 at 03:13

1 Answers1

0

Answering my own question: from what I gather based on people's comments and looking at

it appears that there is no way to get this information in standard C++, and the standard solution is just to provide a library::init() function for the user to call in main().

  • 1
    If this init function is optional and used solely for error reporting, it could have a name reflecting that, such as `library::enhance_error_reporting()`. That said, it will look pretty silly if you ever change the function to become required and/or widen its scope. – chris Dec 10 '22 at 23:32
  • 1
    If the goal is to avoid users mistakenly using the library before initialization, you can make it so that accessing any library functionality requires a library handle. Then initialization can either happen as a local static in the constructor of the handle or the initialization can be reference-counted in a static through the handle constructor and destructor. Then it is impossible for a user to call any library function without constructing the handle and initialization the library first, whether it happens in `main` or before it. – user17732522 Dec 11 '22 at 00:28