C 언어에서 메모리는 프로그램 실행 중 데이터를 저장하고 관리하기 위해 여러 메모리 영역으로 나뉜다. 각각의 영역은 특정 유형의 데이터와 목적에 따라 구분된다.
아래와 같은 순서를 따른다.
+-----------------------+ <- 높은 주소
| 힙 (Heap) | (동적 메모리 할당, 아래로 성장)
|-----------------------|
| 빈 영역 | (힙과 스택 사이의 여유 공간)
|-----------------------|
| 스택 (Stack) | (함수 호출 시 자동 할당, 위로 성장)
|-----------------------|
| BSS 영역 | (초기화되지 않은 전역/정적 변수)
|-----------------------|
| 초기화된 데이터 영역 | (초기화된 전역/정적 변수)
|-----------------------|
| 코드 (Code) | (프로그램 명령어)
+-----------------------+ <- 낮은 주소
1. 코드(Code) 영역
- 설명:
- 실행할 프로그램의 코드(명령어)가 저장되는 영역.
- 기계어 형태로 저장되어 프로세서가 직접 실행한다.
- 특징:
- 읽기 전용: 코드가 수정되지 않도록 보호.
- 프로그램이 시작될 때 메모리에 로드되며, 종료될 때 해제된다.
void myFunction() { /* 이 함수의 명령어가 코드 영역에 저장됩니다 */ }
2. 데이터(Data) 영역
- 설명:
- 프로그램에서 전역 변수와 정적 변수가 저장되는 영역.
- 초기화된 전역/정적 변수와 초기화되지 않은 전역/정적 변수로 나뉜다.
- 구분:
- 초기화된 데이터 영역:
- 명시적으로 초기화된 전역 변수 및 정적 변수가 저장됨.
- 프로그램 시작 시 초기 값으로 설정.
- BSS(Block Started by Symbol) 영역:
- 초기화되지 않은 전역 변수와 정적 변수가 저장됨.
- 자동으로 0으로 초기화됩니다.
- 초기화된 데이터 영역:
- 생명 주기:
- 프로그램 실행 중 지속적으로 유지된다.
int global_var = 10; // 초기화된 데이터 영역
static int static_var; // BSS 영역 (자동 0 초기화)
3. 스택(Stack) 영역
- 설명:
- 함수 호출 시 지역 변수, 매개변수, 반환 주소 등이 저장되는 영역.
- LIFO(Last In, First Out) 구조로 메모리가 할당 및 해제된다.
- 특징:
- 자동으로 할당 및 해제되므로 빠르고 효율적.
- 제한된 크기를 가지며, 초과할 경우 스택 오버플로우가 발생.
- 함수가 호출되면 메모리가 할당되고, 종료되면 해제된다.
void myFunction() {
int local_var = 5; // 스택에 저장
}
4. 힙(Heap) 영역
- 설명:
- 실행 중에 동적으로 할당된 메모리가 저장되는 영역.
- 사용자가 직접 malloc, calloc, realloc, free를 사용하여 메모리를 관리한다.
- 특징:
- 메모리 크기를 유동적으로 조정할 수 있음.
- 할당한 메모리를 명시적으로 해제하지 않으면 메모리 누수(Memory Leak)가 발생.
- 속도가 상대적으로 느리며, 관리가 복잡.
int* ptr = (int*)malloc(sizeof(int) * 10); // 힙에 동적 메모리 할당
free(ptr); // 할당 해제
5. 상수(Constant) 영역
- 설명:
- 문자열 상수 및 const 키워드로 선언된 변수들이 저장되는 영역.
- 특징:
- 읽기 전용이며 수정할 수 없음.
- 상수 문자열은 프로그램 종료 시까지 유지된다.
const int num = 100; // 상수 영역에 저장
char* str = "Hello"; // 문자열 상수가 상수 영역에 저장
~수정중~
1. Const 변수는 어디에 있을까?
ROM(ram이 부족한데 값을 변경하지 않을 때)
2. 초기화 된 전역변수는 어디에?
ROM
3. 초기화 된 전역변수 값은 어디서 불러오는걸까?
4. 초기화 안된 전역 변수는 어디에?
5. 0으로 초기화 하는것과, 초기화 하지 않는 전역변수는 어떠한 차이가 있을까?
전역변수 = ram
rom은 바이트/ 비트단위로 접근하여 값을 지우고 저장할 수 있다.
포인터는 주소값이므로 항상 동일한 데이터 크기를 가진다(자료형과 무관하게)
함수
샷시등은 안전상의 문제로 heap영역 사용 X
Stack
- 80%이상 공간이 넘지 않도록 설계
User stack
R stack
#include <stdio.h>
void modifyValue(int *ptr) { // 함수의 파라미터도 지역변수
int tempvalue = 10;
*ptr = tempvalue; // pointer를 사용하여 num값을 변경
}
int main() {
int num = 5;
printf("변경 전: %d\n", num);
modifyValue(&num); // 함수에 값을 전달
printf("변경 후: %d\n", num);
return 0;
}
call by reference
- 주소값을 넘겨줌
- 값에 대한 오염이 생길 수 있다. (넘겼는데 값을 변경하는 등)
이를 해결하기 위해? const 변수
const변수로 값을 변경하는 걸 막는 건, 컴파일러가.
(page: 0 ~ 256 byte)
Q. stack size를 어떻게 측정할까?
- 스택을 사용하면 값이 오염된다
Q. stack overflow를 어떻게 감지할까?(70% 이상)
'IVS > C 프로그래밍' 카테고리의 다른 글
[C] 구조체 - 바이트 패딩(Byte Padding) (0) | 2025.01.13 |
---|---|
[C] 배열 복사- memcpy, 비교- memcmp (0) | 2025.01.13 |
[C] const 키워드 (0) | 2025.01.13 |
[C/C++] 배열 초기화 - memset, fill (0) | 2025.01.13 |
[C] 형변환, 비트연산자 (1) | 2025.01.13 |