1. Motivations
Sometimes, we need to execute something before and after main(), such as:
- I want to simulate a construtor & destructor in C. I need the invoking count of construtor and destructor strictly be the same. Or else, there may be memory leak.
- To do this, one simple solution is use a global counter to record the invoking times. After main() return/exit, I will check if the counter is 0 or not.
2. Example code
1 #include<stdio.h> 2 3 static g_count = 0; 4 static void _start_before_main(void) __attribute__ ((constructor)); 5 static void _clean_after_main(void) __attribute__ ((destructor)); 6 7 static 8 void _start_before_main() 9 { 10 g_count = 0; 11 printf ("==> start code before main() "); 12 } 13 14 static 15 void _clean_after_main() 16 { 17 if(g_count != 0) 18 { 19 printf("[ERROR!!] constructor() and destructor() NOT match! "); 20 } 21 printf ("==> clean code after main() "); 22 } 23 24 void constructor() 25 { 26 g_count++; 27 } 28 29 void destructor() 30 { 31 g_count--; 32 } 33 34 int main (void) 35 { 36 int i=0; 37 printf ("==> hello, I am main() "); 38 for(i=0; i<10; i++) 39 constructor(); 40 for(i=0; i<11; i++) 41 destructor(); 42 return 0; 43 }
Simply build and run by:
1 $ gcc -o test test.c 2 $ ./test 3 ==> start code before main() 4 ==> hello, I am main() 5 [ERROR!!] constructor() and destructor() NOT match! 6 ==> clean code after main() 7 $
3. How it works
__attribute__ run when a shared library is loaded during loading steps of a C program. Loading happens when a binary file is loading from secondary memory to main memory for CPU execution. In that time many shared libraries like .so files added, typically during program startup. It uses two brackets ((, )) to distinguish them from function calls. GCC attributes are defined like that.
__attribute__ is not a Macro or Function, it is GCC-specific syntax.
It works in C as well as C++ language.
You can get clear understanding of __attribute__ contrutor/destructor from GNU manual:
1 constructor 2 destructor 3 constructor (priority) 4 destructor (priority) 5 The constructor attribute causes the function to be called automatically before execution enters main (). Similarly, the destructor attribute causes the function to be called automatically after main () completes or exit () is called. Functions with these attributes are useful for initializing data that is used implicitly during the execution of the program. 6 7 You may provide an optional integer priority to control the order in which constructor and destructor functions are run. A constructor with a smaller priority number runs before a constructor with a larger priority number; the opposite relationship holds for destructors. So, if you have a constructor that allocates a resource and a destructor that deallocates the same resource, both functions typically have the same priority. The priorities for constructor and destructor functions are the same as those specified for namespace-scope C++ objects (see C++ Attributes). 8 9 These attributes are not currently implemented for Objective-C.
It is working as a constructor and destructor as in OOPS concept. Generally Constructor invokes when an object created; likewise destructor invokes after execution of program automatically.