정렬 알고리즘(버블, 삽입) 만들 떄 의문점.

  • 정렬 알고리즘을 짤떄 이미 배열의 크기의 사이즈가 결정되어있었다.
  • 실제 게임을 하다보면 어느 정도의 데이터 크기가 필요한지 알수가 없을떄가 존재한다.
    • 배열의 고정된 공간안에 배치를 했다면 너무 넉넉하게 잡거나(메모리 낭비) 너무 부족하게 잡을 수도 있다.(메모리 부족)
    • 코드 중으로 미리 할당받는게 아니라 런타임 중에 실시간으로 필요한 메모리를 할당 받거나 해제하는 작업.

실행중에 메모리를 할당받을려는 시도 1.

#include <iostream>

int g_arr[100] = {};

int main()
{
	int arr[100]  = {};
    
    int arr[] = { 1, 2, 3 };
    

}
  • 스택 영역, 데이터 영역은 갑자기 메모리의 크기가 더 필요하면 수정 불가능하다.
  • 배열의 크기를 확정 짓지 않는 경우
    • 불가능, 초기 데이터를 입력하면 그 개수만큼의 배열로 인식된다.
    • int arr[] = { 1, 2, 3 }; -> int arr[3] = { 1, 2, 3,}로 컴파일러는 인식한다.

실행중에 메모리를 할당 받을려는 시도 2.

 int g_ArrSize = 10;
 int g_arr[g_ArrSize] = {}; // 3 오류

int main()
{
	printf("출력\n);
    
    int input;
    scanf_s("%d", &input); // 1
	
    int ArraySize = 100;
    scanf_s("%d", &ArraySize)
    int arr[ArraySize] = {}; // 2 오류 발생.
}
  • 1은 내가 입력 받은 싶은 값에 주소를 아니까 100 값을 입력하고 엔터치면 알려준 주소에 100을 넣는다.
  • 배열의 크기를 변수로 지정하는 경우
  • 런타임(프로그램 실행 중)에 배열의 크기가 확정이 됨.
  • 배열이 선언된 메모리 영역의 크기를 계산 할 수 없다는 뜻.

  • // 2 + // 3 오류 발생 이유
    • 메인 함수가 시작될떄 메인 스택 영역과 데이터 영역의 크기를 할당받고 시작해야되는데 스택 크기를 못잡아서 오류가 난다.
    • 각 함수의 호출 시 할당할 스택의 크기를 확정지을 수 없음.
  • 데이터 영역
    • 프로그램 실행 시 메모리 할당
    • 프로그램 종료 시 메모리 해제
  • 프로그램 실행 중에 데이터 영역의 크기를 변동 시킬 수 없다.
  • 이미 할당과 해제량이 정해진 채로 프로그램이 빌드되어있다.
  • 배열의 크기를 변수로 만든다는 것은 이러한 동작원리를 전부 무시하는 행위이다.

동적할당

  • 런타입 중에 실시간으로 필요한 메모리를 할당 받거나 해제하는 작업
  • 힙 영역을 사용한다.

참고 : 이전 수업에서는 이미 특정 자료형(용도)으로 만들어진 공간을 그 자료형에 맞는 포인터로 가리켜서 원래 목적대로 사용(접근) 했다.

malloc 함수

  • 메모리 할당 함수

  • malloc 함수가 할당받은 공간을 빈 공터라고 생각하면 된다.

  • 동적 할당(malloc 함수)이 할당받은 공간은 용도가 정해지지 않은 빈공터라고 생각 할 수 있다. 따라서 할당받은곳의 주소값만 알고 있으면, 내가 원하는 포인터로 해당 주소를 받아서 그 공간을 원하는(단위 자료형) 으로 접근 및 데이터 쓰기. 읽기가 가능하다.

int main()
{
	int* pInt = nullptr
    void* pData = malloc(100); // 1
}
  • 반환타입이 그래서 void*이다.
    • 특정 자료형으로 해석될 여지를 주지않고, 메모리를 할당 받은 프로그래머가 그곳의 사용 용도를 결정하게 하기 위해서
  • 입력값은 숫자가 들어간다(메모리 사이즈), 그만큼의 크기를 동적할당한다.
  • 시작 주소를 함수의 반환값으로 준다.
int main()
{
	int pInt = (int*)malloc(100);
    pInt[0] = 100;
	pInt[1] = 200;
	pInt[24] = 2500;
    *(pInt + 25) = 200; // pInt[25] = 200; // 1 런타임 에러
    
    free(pInt) // 런타임 에러
    
{
  • 100바이트 할당받았는데 int로 접근하니 할당받은 공간을 25개의 int형 자료형으로 안전하게 쓸수 있다.
  • // 1은 할당 받은 100바이트 공간을 초과하는 상황이지만 컴파일러는 에러라고 보지 않는다.(문법적 오류 x)
    • 초과한 연산에 힙 메모리 영역을 4바이트로 접근한다 이러한 거는 런타임 에러가 발생될 수도 있고 안될 수도 있다.

힙 손상(Heap Corruption)

  • 위의 코드는 지정된 영역을 초과해서 메모리에 데이터를 기록 한다음 데이터를 해제한다
    • 힙손상 발생.
    • 할당받은 공간을 초과하는 일이 발생 하지 않도록 각별히 주의해야한다.
    • 힙 손상 오류는 발생 시 해결까지 광장한 시간이 소요된다.
    • 손상된 마킹값에 새로운 주소가 들어오면 마킹값이 아상해진걸 사용하면 힙 손상이 발생한다.(?)

메모리 종류별 메모리 해제

  • 함수 스택(지역 변수), 데이터 영역(전역 변수)
    • 모든 프로그래머가 직접 메모리를 해제할 필요가 없다.
  • 힙 영역(동적 할당)
    • 프로그램 실행 도중에 얼마든지 할당 받을 수 있는 영역.
    • 대신 프로그래머가 반드시 프로그램 종료 시 메모리를 해제시켜야한다.
    • 해제 시키지 않는다면 그 메모리 영역이 사용중인 상태로 남게된다(메모리 누수(leak))
      • 메모리 누수가 심각하게 누적되면 시스템 메모리 부족 현상으로 재부팅 해야한다.

강의코드

#include <iostream>

int g_ArrSize = 10;
//int g_arr[g_ArrSize] = {};


int main()
{
	//scanf_s("%d", &g_ArrSize);

	printf("출력\n");

	//int input = 0;
	//scanf_s("%d", &input);

	// int arr[] = {1, 2, 3};

	int ArraySize = 100;
	//scanf_s("%d", &ArraySize);
	//int arr[ArraySize] = {}

	//void* pData = malloc(100);
	int* pInt = (int*)malloc(100);
	pInt[0] = 100;
	pInt[1] = 200;
	pInt[24] = 2500;
	//*(pInt + 25) = 200;

	free(pInt);

	return 0;
}

1차 23.12.18
2차 23.12.19
3차 23.12.20
4차 23.12.21
5차 23.12.22
6차 23.12.25
7차 24.01.01
8차 24.01.24

0개의 댓글

Powered by GraphCDN, the GraphQL CDN