안 쓰던 블로그
리눅스 메모리 구조와 값 할당 본문
1. 코드(텍스트) 영역
유저가 작성한 소스코드가 들어가는 영역, 실행할 프로그램의 코드가 바이너리화 되어 저장된다
이곳의 명령 실행 순서는 순차적이지 않다. 왜냐하면 하이레벨 언어 구조가 jump, call 등을 많이 쓰기 때문이다
그래서 순서를 맞추기 위해 EIP 레지스터를 이용한다
EIP 레지스터는 다음에 실행할 명령의 메모리 주소가 저장되어 있는 레지스터로, 현재 실행 중인 명령어가 종료되면 프로세서는 자동으로 EIP 레지스터에 저장된 명령어를 실행한 뒤에 그 다음 명령어를 EIP에 저장한다
프로그램이 실행되면 EIP 레지스터는 코드 영역의 맨 처음 위치로 설정된다
이곳에는 진짜 코드만 저장하고 있기 때문에 쓰기가 금지되어 있다. 읽기만 가능하다
2. 데이터 영역
초기값이 있는 전역(global)변수와 정적(static)변수 등이 할당된다
프로그램 시작과 동시에 할당되며, 프로그램이 종료될 때 메모리가 소멸된다
메모리 접근 공간으로 사용 가능한 공간으로, 프로그램 런타임에 자유롭게 수정 및 변경이 가능하다
#include <stdio.h>
struct Go { int a, b; };
//데이터 영역(데이터 세그먼트)에 할당
int globalval = 1; //초기값이 있는 전역변수
Go go = { 1, 2 }; //초기값이 있는 구조체
static int staticval = 1; //초기값이 있는 정적변수
int main() { return 0; }
3. BSS영역(Block Stated Symbol)
초기값이 없는 전역(global)변수와 정적(static)변수, 0이나 NULL로 초기화된 변수들이 할당된다
BSS 영역은 그런 변수들에게 어느 정도의 메모리를 할당할 것이라는 정보를 저장한다(초기화나 메모리 할당을 하지 않는다)
이후 런타임 시스템이 여기 변수들을 필요로 할 때, 각 변수에 대한 메모리 영역이 실제로 확보된다
초기화는 런타임에 다 링크되어 올라간 뒤에 프로그램 로더가 프로그램을 로드할 때 초기화된다
C언어에서는 초기화 없이 정적으로 변수를 할당하면 데이터의 경우 0, 포인터의 경우 NULL로 초기화해 주는데, 이러한 과정을 거쳐서 되는 것이었다
미리 초기화를 하지 않고 필요할 때 하기 때문에 메모리 사용면에서 BSS가 더 효율적이다
#include <stdio.h>
struct Go { int a, b; };
//BSS 영역에 할당
int globalval; //초기값이 없는 전역변수
Go go; //초기값이 없는 구조체
static int staticval; //초기값이 없는 정적변수(정적변수는 초깃값이 없으면 0이 들어감)
int main() {
return 0;
}
4. 스택 영역
프로그램이 실행하고 있는 동안에 만들어지는 임시 데이터 (지역변수, 매개변수 등)를 스택처럼 쌓아서 저장하는 영역이다
프로그램이 자동으로 사용하는 임시 메모리 영역이라고도 할 수 있다
보통 함수 호출 시 생성되는 지역 변수와 매개변수가 저장되며, 함수 호출이 완료되면 메모리가 소멸된다
컴파일될 때 메모리 공간을 가진다
일반적으로 쓰레드 1개가 1개의 스택을 보유하고, 함수가 호출될 때마다 스택의 일정한 공간(스택 프레임)이 할당된다
#include <stdio.h>
struct Go { int a, b; };
void f1(int a) { //매개변수
int aa = 11; //지역변수
}
int main() {
static int staticval2; //정적변수는 지역변수로 선언되어도 초깃값이 없으면 0이 들어감
int m = 100; //메인도 함수니까 지역변수도 스택 영역에 저장
return 0;
}
main함수도 함수니까 main안에 선언된 지역변수도 스택 영역에 저장된다
a는 매개변수로 임시 데이터니까 스택 영역으로, aa도 지역변수니까 스택 영역에 저장된다
함수가 리턴되면 함수가 사용하던 공간이 반환되며 메모리는 소멸된다
5. 힙 영역
프로그램 실행 중에 동적으로 메모리를 할당하기 위한 공간
malloc등으로 프로그래머가 할당하고 해제한다
이 공간을 동적 데이터 영역이라고도 하며, 여기에 메모리를 할당하는 것을 동적 할당이라고 한다
런타임 시에 동적으로 크기가 결정된다(스택영역은 컴파일 시에 크기가 결정된다)
#include <stdio.h>
#include <stdlib.h>
int main() {
int* arr = (int*)malloc(sizeof(int) * 10); //힙 영역에 메모리 할당
free(arr); //메모리 해제
return 0;
}
이렇게 동적으로 잡은 메모리는 c언어에서는 자동으로 해제되지 않기 때문에 메모리 누수에 빠지지 않기 위해서 free()함수로 직접 해제해주어야 한다
'컴퓨터 구조' 카테고리의 다른 글
컴퓨터 구조-MIPS, MIPS 구조 (0) | 2020.06.08 |
---|---|
컴퓨터구조-캐시 기억장치 (0) | 2020.06.01 |
컴퓨터 구조-분기 명령어, 서브루틴, 0/1/2/3주소 명령어 (0) | 2020.05.30 |
컴퓨터 구조-메모리 구조와 레지스터 (0) | 2020.05.24 |
컴퓨터구조 -명령어를 효과적으로 실행하기 위한 기법 (0) | 2020.05.24 |