LoginSignup
18
12

More than 5 years have passed since last update.

[C/C++][GCC] __attribute__((constructor))でmainの前後で処理を実行

Posted at

__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

18
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
12