일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 변수
- Gain
- 카메라
- 고정비트레이트
- 변수의 초기화와 대입
- 아이리스
- 저조도
- 과초점거리
- 실생활알고리즘
- 조건 제어문
- AppInventer
- camera
- 렌즈
- c언어
- 저장소와 동적메모리
- 심도
- Patch Cleaner
- Zoom Lense
- 이미지센서
- 프로그래머스 lv2
- Pixel Bit Format
- ASCCII
- Digital Slow Shutter
- C Mount
- image sensor
- 간단한 앱만들어보기
- 무게선별자동화
- Depth of Fileld
- CS Mount
- main 함수 인자 전달
- Today
- Total
카메라 개발자 공부방(SW)
[17장] 동적메모리와 저장소 본문
자 오늘은 저장소에 관한 내용과 동적 메모리에 대해 이야기해보겠습니다.
프로그램은 적절한 명령을 통해 주어진 데이터로 가공해서 원하는 결과를 내는 것이 주 역할입니다~!
그런 의미에서 프로그램은 큰 범주에서 명령어와 데이터로 나눌 수 있습니다.
프로그램에 따라 데이터는
1) 잠깐만 필요한 경우가 있고,
2) 프로그램 전반에 메모리가 필요하거나
3) 프로그램이 종료되더라도 계속 살아있어야 되는 경우가 있습니다.
1) 메모리가 잠깐만 필요한 경우
- 연산 과정 중에 나오는 결과를 저장해야 되는 경우
2) 프로그램 전반에 메모리가 필요한 경우
- 메모리가 계속 살아있어야지만 application을 운용할 수 있는 경우
3) 프로그램이 종료되더라도 살아있어야 되는 메모리인 경우
- 파일에 저장된 데이터
- DataBase에 저장된 데이터
- Server에 저장된 데이터
이 데이터와 명령어는 메모리 공간(저장소)에 저장되며 C언어에서는 이를 위한 논리적인 저장소가 따로 존재합니다.
논리적인 저장소는 메모리를 어떤 용도로 사용할 것인지, 사용 주기는 어떻게 할 것인지에 대한 메커니즘도 포함되어있습니다.
그리고 저장소 지정에 대한 키워드도 C언어에서 미리 약속이 되어있습니다.
변수는 선언 위치, 키워드에 따라 메모리 공간의 사용 용도 및 주기가 달라집니다.
Code 영역은 명령어를 저장하는 메모리 공간으로(Source Code logic)에 해당됩니다.
Stack 영역은 블락 {} 안에서만 유효한 메모리 공간입니다.
Global 영역은 프로그램이 시작되고 소멸되는 순간까지 유지되는 메모리입니다.
Heap 영역은 사용자에 의해 할당되는 메모리며, 소멸과 해제를 사용자가 직접 해야 됩니다.
1) 선언 위치 따른 메모리
지역변수 - 블락 {} 안에 선언된 메모리를 의미합니다. {}을 지나게 되면 메모리가 소멸됩니다(Stack 영역).
전역 변수 - {} 외부에 선언된 메모리를 의미합니다. 프로그램이 시작되고 소멸되는 순간까지 유지되는 메모리입니다(Global 영역).
2) 키워드에 따른 메모리
auto - 블락{} 안에서만 유효한 메모리입니다(Stack 영역).
global - 프로그램이 시작되고 소멸되는 순간까지 유지되는 메모리입니다(Global 영역) 하지만 블록 내에 {} 있다면 블록 내에서만 인식 가능합니다.
malloc - 사용자에 의해 생성되고 소멸되는 메모리입니다(Heap 영역).
(extern, register keyword는 다른 챕터에서 다뤄보겠습니다.)
#include <stdio.h>
int main()
{
auto int x = 0; // 지역 변수
return 0;
}
우리가 지금까지 사용했던 변수는 지역 변수(auto)입니다.
#include <stdio.h>
void Print(int x) // 매개변수: stack memory
{
printf("%d\n", x);
}
int main()
{
int x = 0;
Print(x);
return 0;
}
// 실행결과
// 0
매개 변수 역시 지역 변수(auto) 입니다.
#include <stdio.h>
int main()
{
{
int x = 0; // 지역 변수
}
printf("%d\n", x);
return 0;
}
// 실행결과
// Compile error
이런 지역 변수(auto) { } 내에서만 사용할 수 있습니다. (블락을 넘어가면 소멸됩니다.)
전역 변수를 선언하는 방법엔 2가지 방법이 있습니다.
변수를 선언할 때 static 이란 키워드를 붙여서 선언하는 방법과 함수 밖에 선언하는 방법이 있습니다.
#include <stdio.h>
void PrintAutoMemory()
{
int x = 1;
x++;
printf("%d\n", x);
}
void PrintGlobalMemory()
{
static int x = 1;
x++;
printf("%d\n", x);
}
int main()
{
PrintLocalMemory();
PrintLocalMemory();
PrintLocalMemory();
PrintGlobalMemory();
PrintGlobalMemory();
PrintGlobalMemory();
return 0;
}
// 실행결과
// 2
// 2
// 2
// 2
// 3
// 4
static 키워드를 선언해 전역 번수를 생성한 예제입니다.
PrintLocalMemory의 local 변수는 함수를 호출할 때마다 지역변수(int x)가 소멸 됐다 생성 됐다를 반복하니 2가 출력됩니다.
반대로 static으로 선언한 전역 변수는 메모리가 소멸되지 않고 살아있기 때문에 누적해서 증가합니다.
#include <stdio.h>
int g_n;
int main()
{
printf("%d\n", g_n);
return 0;
}
// 실행결과
// 0
이번엔 함수 밖에 전역 변수를 선언한 예제입니다. (전역 변수는 따로 초기화하지 않아도 초기값이 0으로 초기화됩니다.)
static으로 선언한 변수와 함수 밖에 선언된 변수는 같은 전역 변수이지만 아래와 같은 차이점이 있습니다.
1) g_n(전역 변수)는 함수 어디에서나 쓸 수 있습니다.
2_ static으로 선언된 변수는 전역 변수긴 하지만 { } 내에서만 사용이 가능합니다.
메모리는 살아있지만 compile 시간에 변수를 찾지 못하는 문제점이 발생합니다.({} 외부에서 사용하려고 하는 경우)
다음은 동적 메모리 예제입니다.
#include <stdio.h>
#include <malloc.h>
int main()
{
int* pArr = (int*)malloc(4);
*pArr = 42;
printf("%d\n", *pArr);
free(pArr);
return 0;
}
// 실행결과
// 42
malloc 함수는 heap 영역에 메모리를 할당한 후, 메모리에 접근할 수 있는 주소를 반환해줍니다.
그래서 위의 코드를 해석하면 heap영역에 4byte만큼의 메모리를 할당한 후, pArr이란 이름의 포인터로 접근해서 사용한다는 뜻입니다.
메모리 공간을 int*형 point로 반환받았기 때문에 int data type으로 메모리 공간을 사용할 수 있습니다.
만약 위의 메모리를 char*형 point로 반환받으면 char data type의 4개의 메모리 공간을 사용할 수 있습니다.
포인터 타입에 따라 메모리를 자유자재로 사용할 수 있습니다.
사실 코드에 저렇게 숫자를 넣는 코드를 직접 넣어서 쓰는 건 그렇게 좋은 자세가 아닙니다(=매직넘버).
코드의 변화가 온다고 생각해봅시다! 매직넘버를 많으면 코드 수정이 어렵겠죠?
그리고 malloc과 한쌍으로 붙는 것이 free 함수입니다.
free는 전달받은 주소가 가리키는 heap 영역의 메모리를 소멸시키는 역할을 합니다.
free로 메모리를 소멸시키지 않는다면 프로그램이 종료돼도 메모리가 계속 남아있게 됩니다.(메모리 누수 발생)
메모리 누수가 발생되지 않도록 주의해주세요.
#include <stdio.h>
#include <malloc.h>
int main()
{
int* pArr = (int*)malloc(sizeof(int));
*pArr = 42;
printf("%d\n", *pArr);
free(pArr);
return 0;
}
// 실행결과
// 42
메모리를 할당할 땐, 누가 보더라도 명시적으로 작성하는 것이 좋습니다.
#include <stdio.h>
#include <malloc.h>
int main()
{
char* pArr = (char*)malloc(sizeof(char));
*pArr = 'A';
printf("%c\n", *pArr);
free(pArr);
return 0;
}
// 실행결과
// A
char 메모리 데이터 타입입니다.
#include <stdio.h>
#include <malloc.h>
int main()
{
const int BUF_SIZE = 4;
int* pArr = (char*)malloc(sizeof(int) * BUF_SIZE);
// init buffer
for (int k = 0; k < BUF_SIZE; k++)
pArr[k] = 0;
for (int k = 0; k < BUF_SIZE; k++)
pArr[k] = k + 1;
for (int k = 0; k < BUF_SIZE; k++)
printf("%d\n", pArr[k]);
free(pArr);
return 0;
}
// 실행결과
// 1
// 2
// 3
// 4
// 5
malloc으로 할당된 메모리는 초기화가 되어있지 않기 때문에 사용하기 전엔 반드시 초기화를 진행해야 합니다.
비슷한 함수로 calloc을 지원합니다. calloc은 default 값을 0으로 초기화해줍니다.
그래야 잠재적인 문제가 발생하지 않겠죠?
메모리 해제도 신경 써야 합니다.
자 오늘은 여기까지~
'Langauge > C' 카테고리의 다른 글
[19장] 2차원 배열 (0) | 2021.10.08 |
---|---|
[18장] 구조체 (0) | 2021.10.07 |
[16장] 아스키 코드(ASCII) (0) | 2021.10.05 |
[15장] 문자열 라이브러리(string.h) (0) | 2021.10.04 |
[14장] 배열과 문자열 (0) | 2021.10.03 |