[고급 C++]C컴파일러와 C라이브러리(공유/정적/동적라이브러리)
- 컴퓨터공학과/Programming
- 2020. 10. 18.
C 컴파일러 |
#include <stdio.h>
int main()
{
printf("Hello World. \n");
return 0;
}
컴파일러 종류
cc
유닉스에서 사용하는 표준 C 컴파일러
gcc
GNU C 컴파일러로 주로 리눅스 시스템에서 사용함
컴파일 과정
1) 전처리 과정
#define, #include, #if와 같은 지시자 처리
2) 컴파일
전처리 작업을 수행한 소스 코드를 어셈블리 코드로 변환 후 오브젝트 파일로 변환
원시파일의 문맥과 문법을 확인하여 오류가 없으면 소스코드를 기계어 코드로 번역
3) 링크
오브젝트 파일과 라이브러리 함수를 연결하여 실행가능한 실행파일을 생성
CC컴파일 옵션
-o : 실행파일 이름 지정
/data/it/it03]cc hello.c -o hello /data/it/it03]ll 총 304 -rwxr-xr-x 1 it03 jsp 70112 9월 23일 10:05 hello -rw-r--r-- 1 it03 jsp 75 9월 23일 09:43 hello.c drwxrwxrwx 2 it03 jsp 96 9월 23일 08:58 tmp |
-c : 컴파일과 링크 분리
- 컴파일만 하고 링크를 수행하지 않음
- 오브젝트 파일만 생성
/data/it/it03]cc -c hello.c /data/it/it03]ll 총 32 -rw-r--r-- 1 it03 jsp 75 9월 23일 09:43 hello.c -rw-r--r-- 1 it03 jsp 2668 9월 23일 10:07 hello.o drwxrwxrwx 2 it03 jsp 96 9월 23일 08:58 tmp |
-O : 컴파일 최적화
- 실행속도를 향상시키며, 한번 컴파일된 실행파일은 지속적으로 사용되므로 중요
- 특히 O2 옵션은 가장 많이 사용하는 최적화 옵션으로 최적화, 수행되지 않는 코드 제거, 부분적 중복 제거, 연산 강도 경감 등 실행시간이 매우 줄어듦
[ 최적화 예시 (-O) ]
#include <stdio.h>
void delay(int count);
int main()
{
printf("start. \n");
delay(500000000);
printf("end. \n");
return 0;
}
void delay(int count)
{
for (;count > 0; count--)
continue;
}
[ 최적화 옵션 미사용 (-O0) ]
/data/it/it03]cc -O0 loop1.c /data/it/it03]ll 총 256 -rwxr-xr-x 1 it03 jsp 70216 9월 23일 10:59 a.out -rw-r--r-- 1 it03 jsp 210 9월 23일 10:57 loop1.c /data/it/it03]size a.out // 실행파일시 사이즈크기 2848 + 24 + 32 = 2904 /data/it/it03]time a.out // 실행시간 타임 start. end. real 0m3.80s user 0m3.43s sys 0m0.00s |
[ 최적화 옵션 사용 (-O2)]
/data/it/it03]cc -O2 loop1.c /data/it/it03]size a.out 2544 + 32 + 32 = 2608 /data/it/it03]time a.out start. end.
real 0m0.00s user 0m0.00s sys 0m0.00s |
-S : C 소스를 어셈블리 코드로 확인
/data/it/it03]cc -S loop1.c -rw-r--r-- 1 it03 jsp 10851 9월 23일 11:02 loop1.s /data/it/it03]vi loop1.s 57 //file/line/col loop1.c/8/4 58 add out0 = 16, r32 // M [loop1.c: 8/4] 59 add r9 = @pltoff(printf), r0 // I [loop1.c: 8/4] 60 add r14 = r0, gp ;; // I [loop1.c: 8/4] 61 add r9 = r9, gp ;; // M [loop1.c: 8/4] 62 ld8.acq r10 = [r9] // M [loop1.c: 8/4] 63 add r9 = 8, r9 ;; // I [loop1.c: 8/4] 64 ld8 gp = [r9] // M [loop1.c: 8/4] 65 mov b6 = r10 // I [loop1.c: 8/4] |
라이브러리 |
C 라이브러리
라이브러리 특성
컴파일 과정을 거쳐 만든 오브젝트 파일을 한 곳에 만들어 관리하는 아카이브 파일
라이브러리 = 목차(index) + (a.o + b.o + c.o +...)
- c 언어에서 자주 사용되는 함수는 라이브러리로 만들어 매번 컴파일할 필요없이 필요할때마다 사용 가능
- 컴파일 필요없이 링킹만 수행하므로 속도 빠름
- 목차보기 : ar - tv
표준 라이브러리
- 문자열 함수에 대한 선언 : <string.h>
- 문자함수 헤더파일 : <ctype.h>
- 날짜/시간 처리함수 <time.h>
- 동적 메모리함수 <stdlib.h>
사용자 정의 라이브러리
- 사용자가 정의하여 생성한 라이브러리
- 정적/동적/공유 라이브러리
정적 라이브러리
프로그램 실행 이전에, 즉 컴파일 과정의 링킹 단계에서 실행파일에 포함되는 라이브러리
특성
- 오브젝트 파일의 단순한 모음
- 컴파일시 적재되므로 라이브러리를 함께 배포할 필요가 없으며 바이너리 크기가 커짐
- 관리는 편하지만 프로세스마다 중복되어 메모리에 적재
생성 절차
① object 파일 생성
/data/it/it03]cc -c add.c // 오브젝트 파일 생성 /data/it/it03]cc -c sub.c /data/it/it03]cc -c mul.c /data/it/it03]cc -c div.c /data/it/it03]ll *.o -rw-r--r-- 1 it03 jsp 2700 9월 23일 13:30 add.o -rw-r--r-- 1 it03 jsp 2980 9월 23일 13:30 div.o -rw-r--r-- 1 it03 jsp 2732 9월 23일 13:30 mul.o -rw-r--r-- 1 it03 jsp 2700 9월 23일 13:30 sub.o |
② 생성된 오브젝트파일을 아카이브 파일에 추가
- ar -r : 파일이 아카이브내에 존재하지 않으면 추가하고 존재하면 현재버전에 덮어씀
- ar -d : 파일 삭제
/data/it/it03]ar -r libcalc2.a add.o // 오브젝트 파일 아카이브 파일에 추가 ar: libcalc2.a을(를) 만들고 있습니다. /data/it/it03]ar -r libcalc2.a sub.o /data/it/it03]ar -r libcalc2.a mul.o /data/it/it03]ar -r libcalc2.a div.o /data/it/it03]ll -rw-r--r-- 1 it03 jsp 11456 9월 23일 13:33 libcalc2.a
|
※ (기본 경로가 아니므로 라이브러리의 위치 명시) -L 옵션으로 디렉토리를 라이브러리 패스로 설정 필요
* 기본경로 : /lib, /usr/lib, /usr/local/lib
/data/it/it03]cc calc.c -lcalc2 // 라이브러리 경로 알수없으므로 에러 발생 Fatal error.
|
/data/it/it03]cc calc.c -L. -lcalc2 // 라이브러리 패스 설정 /data/it/it03]a.out x ? 100 y ? 30 100 + 30 = 130 100 - 30 = 70 100 * 30 = 3000 100 / 30 = 3 |
공유 라이브러리
프로그램 실행 시 실행파일에 포함되는 라이브러리
특성
- .so 확장자
- 실행시 적재하며 함수를 찾아야하므로 시간 소요
- 공유라이브러리를 사용하는 모든 프로세스들이 이미 메모리에 로드되어있는 하나의 공유라이브러리를 공유해서 사용
- 실행시 라이브러리를 적재하므로 프로그램 배포 시 공유라이브러리도 함께 배포해야함
생성 절차
① object 파일 생성
-ePIC 옵션은 위치에 독립적인 코드를 만들어줌
/data/it/it03]cc -c -ePIC add.c |
② 공유라이브러리는 ar이 아닌 cc 컴파일러에서 생성
/data/it/it03]cc -b -o libcalc3.so add.o sub.o mul.o div.o /data/it/it03]ll 총 528 -rwxr-xr-x 1 it03 jsp 77832 9월 23일 13:52 libcalc3.so |
※ 공유라이브러리 패스 설정
- LD_LIBRARY_PATH라는 환경변수를 통하여 경로를 읽어오기 때문에 경로가 설정되어야함
export LD_LIBARY_PATH=$LD_LIBRARY_PATH:/disk1/tutor1/lib |
※ 실행파일이 요구하는 라이브러리 목록 확인
/data/it/it03]ldd a.out a.out: libcalc3.so => ./libcalc3.so libc.so.1 => /usr/lib/hpux32/libc.so.1 libdl.so.1 => /usr/lib/hpux32/libdl.so.1 |
동적 라이브러리
프로그램 시작때가 아닌 실행중 로딩되는 라이브러리
특성
- 플러그인, 모듈 구현 시 적합
- 필요할 때까지 로드를 기다림
- API를 통해 사용
* dlopen : 라이브러리 열기
* dlsym : 함수 주소 반환
예제
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
void (*add)(int, int); //함수포인터 변수 선언
void (*sub)(int, int);
void (*mul)(int, int);
void (*div2)(int, int);
int main()
{
void *handle;
int x, y;
handle=dlopen("libcalc3.so",RTLD_LAZY); //동적 라이브러리 load
if(!handle)
{
perror(dlerror);
exit(1);
}
add=(void (*)(int,int))dlsym(handle, "add"); //함수포인터 변수에 함수주소
sub=(void (*)(int,int))dlsym(handle, "sub");
mul=(void (*)(int,int))dlsym(handle, "mul");
div2=(void (*)(int,int))dlsym(handle, "div");
printf("x ? ");
scanf("%d", &x);
printf("y ? ");
scanf("%d", &y);
if(add) add(x,y); //함수 포인터 변수를 사용하여 함수호출
if(sub) sub(x,y);
if(mul) mul(x,y);
if(div2) div2(x,y);
dlclose(handle); //동적 라이브러리 닫기
return 0;
}
시리즈 더 보기
[고급 C++]C컴파일러와 C라이브러리(공유/정적/동적라이브러리)
[고급 C++]포인터 1편(프로세스/포인터변수/포인터연산/NULL포인터)
궁금한 사항은 댓글로 남겨주세요💃💨💫
좋아요와 구독(로그인X)은 힘이 됩니다 🙈🙉
'컴퓨터공학과 > Programming' 카테고리의 다른 글
[고급 C++]포인터 1편(프로세스/포인터변수/포인터연산/NULL포인터) (0) | 2020.10.20 |
---|---|
[고급 C++]조건 컴파일 / make (0) | 2020.10.19 |
[C++]최대공약수 구하기(3가지 방법, 유클리드 호제법) (0) | 2020.05.05 |
[C++] 누구나 쉽게, 리팩토링(클린코드)-⑤ NULL체크를 위한 널 객체 (0) | 2020.04.18 |
[C++] 객체지향 개념(객체/클래스/생성자) 및 헤더파일 분리 요약정리 (0) | 2020.04.13 |