__attribute__((constructor))
の検証と使用方法まとめ
GCCの拡張のため、どこででも動作するわけではないので注意
ソース内に含める場合
main.c
#include <stdio.h>
__attribute__((constructor))
static void constructor() {
puts("constructor");
}
__attribute__((destructor))
static void destructor() {
puts("destructor");
}
int main(int argc, char const* argv[])
{
puts("call main");
return 0;
}
ビルドと実行結果
$ gcc main.c && ./a.out
constructor
call main
destructor
共有ライブラリとしてリンクする場合
main.c
#include <stdio.h>
int main(int argc, char const* argv[])
{
puts("call main");
return 0;
}
sharedlib.c
#include <stdio.h>
__attribute__((constructor))
static void constructor() {
puts("constructor");
}
__attribute__((destructor))
static void destructor() {
puts("destructor");
}
ビルドと実行結果
$ gcc -shared -fPIC sharedlib.c -o libconstructor.so
$ gcc main.c -L . -lconstructor
$ LD_LIBRARY_PATH=. ./a.out
constructor
call main
destructor
LD_PRELOADを使用する場合
LD_PRELOADを使用することで、後から任意のプログラムに処理を追加することもできる
main.c
#include <stdio.h>
int main(int argc, char const* argv[])
{
puts("call main");
return 0;
}
preload.c
#include <stdio.h>
__attribute__((constructor))
static void constructor() {
puts("constructor");
}
__attribute__((destructor))
static void destructor() {
puts("destructor");
}
ビルドと実行結果
$ gcc main.c && ./a.out
call main
$ gcc -shared -fPIC preload.c -o preload.so
$ LD_PRELOAD=./preload.so ./a.out
constructor
call main
destructor
__attribute__((constructor))
が複数ある場合
__attribute__((constructor))
が複数存在する場合でも問題なく動作する。
(ただし実行順に関しては不明、実行順に依存がある処理は避けたほうがよさそう)
main.c
#include <stdio.h>
__attribute__((constructor))
static void constructor1() {
puts("constructor1");
}
__attribute__((destructor))
static void destructor1() {
puts("destructor1");
}
int main(int argc, char const* argv[])
{
puts("call main");
return 0;
}
preload.c
#include <stdio.h>
__attribute__((constructor))
static void constructor2() {
puts("constructor2");
}
__attribute__((destructor))
static void destructor2() {
puts("destructor2");
}
ビルドと実行結果
$ gcc main.c && ./a.out
constructor1
call main
destructor1
$ gcc -shared -fPIC preload.c -o preload.so
$ LD_PRELOAD=./preload.so ./a.out
constructor2
constructor1
call main
destructor1
destructor2
参考
main() の前に関数を呼ぶ - bkブログ
c++ - How exactly does attribute((constructor)) work? - Stack Overflow
GCC の attribute((constructor)) を使ってみる:Book of Days
gcc - C++ static initialization vs attribute((constructor)) - Stack Overflow