(작성중) shared lib
2026. 4. 10. 17:36
`__attribute__((constructor))`를 사용한 간단한 예제를 보여드릴게요.
## 개념 설명
`__attribute__((constructor))`는 GCC/Clang 확장으로, **shared library가 로드될 때 자동으로 실행**되는 함수를 지정합니다.
- `dlopen()` 또는 링크 시 로드 시점에 호출
- `main()` 보다 먼저 실행
- 반대로 `__attribute__((destructor))`는 unload 시 실행
---
## 파일 구조
```
mylib/
├── mylib.cpp # shared library
├── mylib.h
└── main.cpp # 사용하는 쪽
```
---
## mylib.h
```cpp
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
void mylib_hello();
#ifdef __cplusplus
}
#endif
```
---
## mylib.cpp
```cpp
#include <stdio.h>
#include "mylib.h"
// 라이브러리 로드 시 자동 실행
__attribute__((constructor))
static void mylib_init() {
printf("[mylib] constructor: library loaded!\n");
}
// 라이브러리 언로드 시 자동 실행
__attribute__((destructor))
static void mylib_fini() {
printf("[mylib] destructor: library unloaded!\n");
}
void mylib_hello() {
printf("[mylib] hello() called\n");
}
```
---
## main.cpp (정적 링크 방식)
```cpp
#include <stdio.h>
#include "mylib.h"
int main() {
printf("[main] main() start\n");
mylib_hello();
printf("[main] main() end\n");
return 0;
}
```
---
## main_dlopen.cpp (동적 로드 방식)
`dlopen()`으로 런타임에 명시적으로 로드하는 경우:
```cpp
#include <stdio.h>
#include <dlfcn.h>
int main() {
printf("[main] before dlopen\n");
// 라이브러리 로드 → 이 시점에 constructor 호출됨
void* handle = dlopen("./libmylib.so", RTLD_LAZY);
if (!handle) {
fprintf(stderr, "dlopen error: %s\n", dlerror());
return 1;
}
printf("[main] after dlopen\n");
// 함수 포인터 획득
typedef void (*hello_fn)();
hello_fn fn = (hello_fn)dlsym(handle, "mylib_hello");
if (fn) fn();
printf("[main] before dlclose\n");
// 라이브러리 언로드 → destructor 호출됨
dlclose(handle);
printf("[main] after dlclose\n");
return 0;
}
```
---
## 빌드 & 실행
```bash
# shared library 빌드
g++ -shared -fPIC -o libmylib.so mylib.cpp
# ── 방법 1: 정적 링크 ──
g++ -o main_static main.cpp -L. -lmylib -Wl,-rpath,.
./main_static
# ── 방법 2: dlopen ──
g++ -o main_dl main_dlopen.cpp -ldl
./main_dl
```
---
## 예상 출력
**정적 링크:**
```
[mylib] constructor: library loaded! ← main() 이전
[main] main() start
[mylib] hello() called
[main] main() end
[mylib] destructor: library unloaded! ← main() 이후
```
**dlopen:**
```
[main] before dlopen
[mylib] constructor: library loaded! ← dlopen() 시점
[main] after dlopen
[mylib] hello() called
[main] before dlclose
[mylib] destructor: library unloaded! ← dlclose() 시점
```
---
## 우선순위 지정 (여러 constructor가 있을 때)
```cpp
__attribute__((constructor(101))) void init_first() { /* 먼저 실행 */ }
__attribute__((constructor(102))) void init_second() { /* 나중 실행 */ }
```
숫자가 작을수록 먼저 실행됩니다. `0~100`은 시스템 예약이므로 `101` 이상 사용을 권장합니다.
