
정보처리기사 실기를 공부하게 되면서 기초이면서 꼭 알아야 하는,
컴파일과 런타임에 있어서 어떠한 차이가 있는지 간단하게 작성하고자 한다.
여기서 공부하고자 하는 컴파일 시점과 런타임의 시점은
C, Java, Python은 공통 개념으로 메모리 구조와 동적 메모리 할당을
이해하기 위한 배경 지식이라고 볼 수 있다.
아래 표는 컴파일과 런타임의 각각 시점을 핵심으로 정리한 내용이다.
| 구분 | 컴파일 시점 | 런타임 시점 |
|---|---|---|
| 시점 | 소스 코드 ➡️ 실행 파일 변환 시 | 프로그램 실행 중 |
| 결정 | 배열 크기, 지역 변수 크기, 타입 | malloc 크기, 사용자 입력 |
| 오류 | 문법 오류, 타입 오류 | 0으로 나누기, 널 포인터 접근 |
컴파일(Compile)은 사람이 작성한 소스 코드를
컴퓨터가 이해할 수 있는 기계어로 변환하는 과정이다.
// hello.c
# include <stdio.h>
int main() {
printf("Hello, worild!\n");
return 0;
}
위 코드를 컴파일을 하면,
실행 가능한 파일이 생성된다.
gcc hello.c -o hello // 컴파일
./hello // 실행
런타임(Runtime)은 프로그램이 실제로
실행되는 시점을 의미한다.
| 단계 | 설명 |
|---|---|
| 1. 작성 | 소스 코드 작성 (.c 파일) |
| 2. 컴파일 | 소스 코드 ➡️ 실행 파일 변환 |
| 3. 런타임 | 실행 파일을 실행하는 시점 |
런타임에는 사용자 입력을 받거나, 파일을 읽거나, 네트워크 통신을 하는 등
실행 중에만 알 수 있는 일들이 발생한다.
int n;
scanf("%d", &n); // 런타임에 사용자가 입력한 값으로 n이 결정
컴파일러가 코드를 분석할 때 미리 알 수 있는 것들이다.
int arr[10]; // 컴파일 시 40바이트로 결정(int 4바이트 * 10)
배열 크기는 컴파일 시점에 상수로 지정해야 한다.
int n = 10;
int arr[n]; // 컴파일 오류 가능 (C89 표준)
// C99 이후에는 VLA로 허용되나 권장하지 않음
void func() {
int a; // 4바이트 - 컴파일 시 결정
double b; // 8바이트 - 컴파일 시 결정
char str[100]; // 100바이트 - 컴파일 시 결정
}
함수 호출 시 스택에 얼마만큼의 공간이 필요한지
컴파일러가 미리 계산한다.
sizeof(int); // 4 - 컴파일 시 결정
sizeof(double); // 8 - 컴파일 시 결정
sizeof(char); // 1 - 컴파일 시 결정
sizeof 연산자의 결과값은 컴파일 시점에 확정된다.
프로그래밍 실행 중에만 알 수 있는 것들이다.
int n;
printf("배열 크기를 입력하세요: ");
scanf("%d", &n);
// 런타임에서 n의 값에 따라 메모리 크기가 결정
int *arr = (int*)malloc(sizeof(int) * n);
동적 메모리 할당은 런타임에 크기를 결정할 수 있는 대표적인 방법이다.
char name[50];
printf("이름을 입력하세요: ");
scanf("%s", name); // 런타임에 사용자가 입력
int x = rand() % 100; // 런타임에 난수 생성
if (x > 50) {
printf("큰 수"); // 실행될 지는 런타임에 결정
} else {
printf("작은 수");
}
FILE *fp = fopen("data.txt", "r");
// 파일 내용은 런타임에만 알 수 있음
컴파일 에러는 컴파일 과정에서 발견되는 오류이다.
프로그램이 아예 실행 파일로 만들어지지 않는다.
// 문법 오류 - 컴파일 에러
int a = 10 // 세미콜론 누락
printf("%d", a);
// 타입 오류 - 컴파일 에러
int *p = "hello"; // int* 에 문자열 대입 시도
| 컴파일 에러 종류 | 예시 |
|---|---|
| 문법 오류 | 세미콜론 누락, 괄호 불일치 |
| 타입 불일치 | int에 char* 대입 |
| 선언되지 않은 변수 | prinft (오타) |
| 잘못된 연산 | 10 + "hello" |
런타임 에러는 프로그램 실행 중에 발생하는 오류이다.
컴파일은 성공했지만 실행 중에 문제가 생긴다.
// 0으로 나누기 - 런타임 에러
int a = 10;
int b = 0;
int c = a / b; // 실행 시 오류
// 널 포인터 접근 - 런타임 에러
int *p = NULL;
*p = 100; // 실행 시 오류
// 배열 범위 초과 - 런타임 에러 (또는 예기치 않은 동작)
int arr[5];
arr[100] = 10; // 위험한 접근
| 런타임 에러 종류 | 예시 |
|---|---|
| 0으로 나누기 | a / 0 |
| 널 포인터 역참조 | *NULL |
| 배열 범위 초과 | arr[1000] (크기가 10인 배열) |
| 스택 오버플로우 | 무한 재귀 호출 |
| 메모리 부족 | 너무 큰 malloc |
| 런타임 에러 종류 | 예시 | 예시 |
|---|---|---|
| 언제 | 코드 ➡️ 실행 파일 변환 시 | 프로그램 실행 중 |
| 메모리 할당 | 스택 변수, 배열 크기 | malloc, 동적 배열 |
| 오류 발견 | 문법, 타입 오류 | 논리 오류, 예외 상황 |
| 오류 시 | 실행 파일 생성 안됨 | 프로그램 비정상 종료 |
위 개념을 이해해야 이후에 메모리 구조에서의
스택과 힙의 차이, 동적 메모리 할당에서 malloc이
필요한 이유를 더 잘 이해할 수 있다.