views:

1360

answers:

2

It seems pretty clear that it is supposed to set things up.

  1. When exactly does it run?
  2. Why are there two brackets?
  3. Is __attribute__ a function? A macro? Syntax?
  4. Does this work in C? C++?
  5. Does the function it works with need to be static?
  6. When does __attribute__((destructor)) run?

Example in Objective C:

__attribute__((constructor))
static void initialize_navigationBarImages() {
  navigationBarImages = [[NSMutableDictionary alloc] init];
}

__attribute__((destructor))
static void destroy_navigationBarImages() {
  [navigationBarImages release];
}
+14  A: 
  1. It's run when a shared library is loaded, typically during program startup.
  2. That's how all GCC attributes are; presumably to distinguish them from function calls.
  3. GCC-specific syntax.
  4. Yes.
  5. No.
  6. The destructor is run when the shared library is unloaded, typically at program exit.

So, the way the constructors and destructors work is that the shared object file contains special sections (.ctors and .dtors on ELF) which contain references to the functions marked with the constructor and destructor attributes, respectively. When the library is loaded/unloaded the dynamic loader program (ld.so or somesuch) checks whether such sections exist, and if so, calls the functions referenced therein.

Come to think of it, there is probably some similar magic in the normal static linker, so that the same code is run on startup/shutdown regardless if the user chooses static or dynamic linking.

janneb
The double brackets make them easy to "macro out" (`#define __attribute__(x)`). If you have multiple attributes, e.g., `__attribute__((noreturn, weak))`, it'd be hard to "macro out" if there were only one set of brackets.
Chris Jester-Young
It isn't done with `.init/.fini`. (You can validly have multiple constructors and destructors in a single translation unit, nevermind multiple in a single library -- how would that work?) Instead, on platforms using ELF binary format (Linux, etc.), the constructors and destructors are referenced in the `.ctors` and `.dtors` sections of the header. True, in the old days, functions named `init` and `fini` would be run on dynamic library load and unload if they existed, but that's deprecated now, replaced by this better mechanism.
ephemient
@ephemient: Thanks, I had forgot about the new and improved way of doing things. Answer updated accordingly.
janneb
FYI: In the gcc online documents (http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html) it says the following under "constructor, destructor": "These attributes are not currently implemented for Objective-C."
cheshirekow
+2  A: 

Excellent answer by @janneb, very useful. Just for completeness, here is a link to the related GCC docs.

I'm glad I stumbled onto this question, it just allowed me to eliminate two dozen lines of boilerplate code and redundant function calls for doing some library-wide initialization in my Objective-C framework.

NOTE: Although this syntax is specific to GCC, LLVM and Clang have been written to support it as well, and code compiled using Clang-LLVM seems to work just like GCC-compiled code.

Quinn Taylor