본문 바로가기
TIL/따배씨

Storage Classes, Linkage, and Memory Management (2021-01-21~2021-01-22)

by Dev_Dank 2021. 1. 21.

12.1 메모리 레이아웃 훑어보기

C 언어로 작성한 프로그램이 메모리에서 어떻게 사용되는지에 대한 내용이다. 

프로그램을 실행시키려면 프로그램이 메모리에 올라가야하고 내용이 변경되면 안된다. 그래서 Text segment에 프로그램코드가 올라가고 해당 부분을 수정하려하면 운영체재가 막는다. 
전역변수는 빨간칸 안에 저장되고 프로그램이 끝날때 까지 메모리에 남아있는다.

주의 할점은 초기화 되지않은 전역/정적변수는 BSS에 저장되고 그공간에 있는것들은 프로그램이 시작 될때 0으로 초기화됨. 오히려 한꺼번에  모아서 0으로 초기화 해주기위해 BSS에저장된다고 생각할것

지역변수는 스택이라는 메모리에 저장되며 스택은 필요할때 늘어났다 아닐때 줄어드는 특성이 있음.
메모리공간이 얼마나 필요할지 컴파일할때 모르면 힙에 저장됨.

12.2 객체와 식별자, lvalue와 rvalue

객채와 식별자의 구분. 

12.3 변수의 영역과 연결 상태, 객체의 지속 기간

file 스코프를 지닌 전역 변수 의 사용은 이하와 같다. 

전역변수 초기화를 안해줘도 0으로 자동으로 초기화되어 출력되는 점에 주의 하자. 이유는 12.1강에 나왔음. 

file 스코프에 있는변수는 프로그램 전체에서 사용할수 있는것처럼 사용이 가능해서 전역변수라고 부른다. 

Lecture12.3B 파일에서 선언한 el 함수를 Second 파일에서 extern int el; 을 통해 가져와 사용하는 모습이다. 

file 스코프에 있는변수를 static과 함께 선언하면 해당 파일 내부에서만 쓸수있게 범위가 아래사진처럼 제한된다. 

static으로 선언한 변수를 다른 파일에서 사용하려하니 에러가 발생.

Duration이란 메모리에 존재하는 기간을 의미하며 4가지가 존재한다.

- static storage duration  :프로그램이 시작때부터 끝날때까지 계속 메모리에 static 하게 존재 한다는 것 
- automatic storage duration  //스택과 관련있음.
- allocated storage duration  //동적할당과 관련있음.
- thread storage duration     

함수내에서 static으로 선언한 ct는 main함수로 가도 1이 그대로 더해져서 출력되는 모습이다. 

12.4 저장 공간의 다섯 가지 분류

변수가 저장되는것을 5가지로 나눠 볼 수있다. 

C에서 번역 단위는 파일로 생각하면 된다. 

12.5 자동 변수

Automatic storage class를 사용하는 변수

지금까지 사용해온 지역변수는 사실 Automatic storage class 었음. 프로그램 전체에서 계속 사용할 변수가 아니라면 계속 메모리에 놔둘 필요가 없음 -> 사용하지 않을때 다른 변수가 사용할 수 있도록 자리를 내줌.

그리고 지속기간이 자동으로 바껴서 Linkage가 안됨(외부로 연결이 안됨). 

블럭이나 함수헤더에 선언된것이 이 유형에 포함됨 스택과 스택프레임에대한 간략 한 설명은 13분 23초 참고.나머지부분은 기존 지역변수 설명강의에서의 내용과 동일하여 따로 정리하지 않겠음. 

12.6 레지스터 변수

레지스터는 CPU의 일부로 CPU가 가지고 있는 임시작업공간이다.

메모리는 CPU와 물리적으로 다른곳에 있고 버스를 통해 서로 데이터를 주고 받는다고 배웠었음 -> 데이터를 주고받는데 시간이 어느정도 걸림

레지스터는 메모리처럼 데이터를 가지고 있을수 있는데 CPU의 일부라 엄청 빠르게작동한다. -> 빠르게 작동하는 프로그램이 필요할때 변수를 레지스터에 놓고 사용해야 할때가 있음. 

메모리의 위치가 레지스터 또는 스택인 이유는 프로그래머가 register 키워드를 사용해서 register에 요청을 해도 컴파일러가 레지스터에 놓을때도 또는 스택에 놔서 사용을 할때도있음. 

실제 사용은 이하와 같이 한다. 

12.7 블록 영역의 정적 변수

main함수에서 count()를 2번 연속실행할때는 같은 작업을 2번하는거라 스택에서 굳이 뺏다꺼냇다 안해서 주소가 안바뀌지만 counter_caller()같이 다른 스택프레임을 통해서 호출하면 주소값이 확실히 달라지는걸 볼수있다. Static으로 선언한 함수는 정적메모리에 데이터가 저장되기 때문에 주소값이 계속 일정한것을 볼 수 있음. 
함수의 인자로 static을 넣으면 문제가 발생한다. 

12.8 정적 변수의 외부 연결 external linkage

기본적인 선언방법은 이하와 같다.

referencing declaration은 extern을 붙여서 사용할 수 있다. 

다른 파일에서 쓰려면 
1. 전역변수로 선언하거나
2. 지역변수로 스코프내에 일일이 extern과 함께 referencing declaration을 할 수 있다. 

 

second.c 파일에서 Lecture12.8_main.c 파일의 g_int를 전역 변수로 설정하여 사용.. 
second.c 파일에서 Lecture12.8_main.c 파일의 g_int를 각 함수의 스코프내에서 일일히 가져와서 사용.

12.9 정적 변수의 내부 연결 internal linkage

file scope 선언앞에 static을 붙이면 해당 파일에서만 사용가능한 변수가됨.

12.11 함수의 저장 공간 분류

함수는 external이 기본이고 static도 가능함. 디폴트로 함수는 프로그램과함께 로딩되어 메모리에 계속있음
기본적으로 함수선언은 extern으로 여겨짐. (기본함수 선언은 extern을 생략이 가능한거임)

함수에 static을 붙여주면 함수의 사용 스코프가 제한됨. 

Second.c 에서 static 선언된 함수를 Lecture12.11.c에서 사용하려니 문제가 발생하는 모습

static은 프로토타입에만, 함수의 바디에만, 둘다 붙여도 문법적으로 ok

함수의 프로토 타입에서만 static
함수의 바디에 static
두곳 다 static 

12.13 메모리 동적 할당

"동적 = 컴파일타임이 아니라 런타임에 결정된다는 것"

동적할당 메모리는 포인터만 가져오고 인식자가 없음. 
필요한 메모리를 컴파일 타임에 알수없고 런타임이 되어야만 알수있을때 동적할당 메모리를 사용한다.

동적할당 메모리를 받아올때는 malloc()을 사용한다. 그리고 메모리를 다사용했으면 free()를 꼭 사용해줄것

기본적인 사용법은 이하와 같다. 

malloc안에 할당받을 사이즈를 넣어주고 활용할 포인터에 맞게 캐스팅(형변환)을 해주면 됨.

malloc은 줄수있는 메모리 공간이 없으면 NULL 포인터를 리턴하며 이하와 같이 대응 할 수 있다. 

동적할당으로 받은 메모리를 다썻으면 free를 해줘야하는데 결국 포인터는 별도의 변수기 때문에 free이후의 포인터변수의 주소는 변화하지 않는다. (그래서 다쓴 동적할당 메모리의 포인터는 NULL 포인터로 바꿔주는게 좋음

동적할당 메모리는 배열처럼 사용할 수 있다. 

배열안의 원소의 값을 초기화를 안해주면 쓰레기 값이 들어있는 상태다. 

초기화를 안해준 상태에서는 쓰레기 값이 들어있는 상태.

12.14 메모리 누수와 free()의 중요성

강의 전반의 내용은 꼭 free()를 해줘야 한다는 거였다. 안해주면 메모리누수가 일어난다는 것. 

12.15 동적 할당 메모리를 배열처럼 사용하기

동적할당 메모리는 이하의 예시처럼 1차원 배열처럼 이용할 수 도 있다. 

이하처럼 열과 행을 상수로 선언하여 2차원 배열처럼도 사용가능 

그러나 상수로 사용하는것은 별의미가 없어서 이하처럼 사용하는게 더 많다. 

12.16 calloc(), realloc()

calloc과 malloc은 기능상 똑같은데 문법적으로 받는 인자가 2개라는게 다르다. 그리고 calloc은 0으로 초기화를 해준다는 점이 다르다. 

realloc은 동적할당으로 받은 메모리크기를 조정할수 있다. 그리고 추가된 공간에 대해 초기화를 해주지 않아서 쓰래기값이 존재하게 된다. 

12.18 자료형 한정자들 const, volatile, restrict

const는 기존의 내용과 같아서 생략. volatile은 내가 선언한 변수가 컴파일러가 모르는 상황에서 바뀔수도 있다고 명시 해주는것.restrict는 데이터 오브젝트에 접근하는게 이거 하나뿐이다고 주장하는것. 

 

댓글