How to create / create an instance of a class before any other global or static variable?

How to create an instance of a certain class earlier than main (), earlier than any other instance (including static and global variables, including in static and dynamic libraries (including libraries provided by third parties))?


I am dealing with a project with a number of classes, which during construction can cause an error, for example. access the null pointer. Any such error causes a signal to be sent to the application. I have a signal handler that catches signals, shows the stack trace of the abusive stream and calls the default signal handler, which leads to the generation of a core dump, etc.
However, some of these error instances are created as global variables and static class variables. That is, they are created and cause a signal earlier than main ().

To catch such signals, I need to register a signal handler earlier than in main (), i.e. I need to create an instance (which the signal handler will register) as well as a global or static class variable, and I need to ensure that such an instance is created / created before any other instance.

How to do it?


To register a signal handler, I use sigaction () .
To show the stack trace, I use backtrace () , backtrace_symbols () , abi :: __ cxa_demangle () .

+7
c ++ linux
source share
6 answers

Standard C ++ does not provide a way to arrange initializers between translation units, but gcc does. Example from https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html :

Some_Class A __attribute__((init_priority (2000))); 

The lowest value (highest priority) is 101.

+3
source share

The order in which static constructors are called depends on their order in the source file, the linking order, and the load order of the shared libraries. The usual way to do what you need is to create a separate file with your registration function and make sure that the corresponding object is displayed as the very first on the linker command line. It should not be part of any shared or static library.

i.e. first.c

 static int first_function() { // register your signals ... return 0; } static int status = first_function(); gcc -c first.c -o first.o gcc -o myexec first.o ... all other files 
+2
source share

You can create a small project or executable file outside the main application, which is compiled and created separately as part of your own solution. However, this small application will have the required command line argument, which is necessary to work with your main application with which you want to test. The command line argument is the path to the place where the main path or directory of the project folder is located, which will contain the header file that works with this external application. Then, depending on which IDE you are using, you will need to make some settings for your IDE to configure the correct paths.

For example, if you work in MS Visual Studio. You can right-click on the launch project and select properties, and then on the properties page on the left side there is a section called Build Events , and then, if you expand this section, you will get three options: Pre-Build Event , Pre-Link Event and Post-Build Event all three of them have the same fields on the right side for their settings: Command Line , where you will need to set your paths, Description all that you want to use to describe the build event command, and Use In Build which in basically is a boolean switch Y/N

Now the other IDEs will differ in how they are configured and options are available, but something like that may suit your needs. Forgive me in the example above, which uses Microsoft Visual Studio, since I am not familiar with Linux. However, I believe that something like this can be done; it's just a matter of knowing your compiler, linker, and debugger.

+1
source share

There may be a requirement using static fuction variables.

 class A; A & GetA() { static A internal_a; return internal_a; } ... class B { public: B() { auto &a = GetA(); a.DoSomething(); } } ... B global_b; ... 

Whenever constructor B is called, calling 'GetA', the static function variable 'internal_a' is initialized before it is used again.

See also. What is the lifetime of a static variable in a C ++ function?

This method is also described in Scott Meyers' book Effective C ++.

+1
source share

It is impossible to do this, unfortunately, if you do not have access to the source (which is excluded, since you have third-party libraries).

If you do something like this:

 // Foo.h inline fooGlobal() { static Foo f; return f; } static auto& foo = fooGlobal(); 

Then you can guarantee that any file that includes Foo.h will see foo initialized before any globals in this file. If your third-party libraries define global tables in header files (using a trick like the one above to prevent multiple global variables from being received), you can make sure that in all Foo.h you include Foo.h before the third-party header. But if the third-party library has global values ​​defined in the .cpp file, you can absolutely do nothing in terms of pure C ++, shy to crack this code.

Now you can do one thing if you are really desperate: you can define your global in a shared library and use the LD_PRELOAD trick to ensure that your shared library loads before anything else: What is the LD_PRELOAD trick? . This is pretty hacky, but if you have binary code, you have full control over it (i.e. you do not distribute it to clients, but simply to a server that you run yourself), then this can be quite good.

0
source share

(Providing a temporary answer to my question)
Based on

  • this answer is from @Serge,
  • this answer is from @ToddFleming,
  • and this is my own observation

final answer seems

  • to create a global instance in a .CPP file,
  • add __attribute__ ((init_priority (101))) to this instance,
  • To list this file first in the linker list for the dynamic / shared library,
  • Create a dynamic / shared library
  • load this library primarily into other dynamic / shared libraries.

This solution has not been fully verified (I hope I will check it later).


If you decide to vote for this answer, then instead (or, at least in addition) better vote for the other answers mentioned above.

0
source share

All Articles