void* malloc(size_t size);
매개변수(인자)
size_t size = size 바이트만큼 메모리를 할당받는다.
반환값(리턴값)
* 주소를 반환한다. (void*)
실패 시 NULL
설명
* 스택 메모리를 사용하기 위한 함수.
* malloc은 memory allocation이라는 뜻이다.
* #include <stdlib.h>가 있어야 한다.
* 할당/해제를 수동으로 해야 하며 힙보다 느리다.
* 할당받은 메모리에는 쓰레기 값이 들어있다.
할당을 실패했다면?
* 함수가 실패했다면 NULL을 반환하니 실패 여부는 쉽게 알 수 있다.
하지만 malloc 같은 동적 메모리 할당 함수의 실패는 우리가 해결할 수 없는 경우가 많다.
* 메모리 공간이 부족해서 함수가 NULL을 반환했다면 우리가 뭘 어쩌겠는가?
실패할 수 있는 경우를 제거하고, NULL을 반환했을 때의 예외를 생각하지 말자.
동적 메모리의 사용
* 언제 사용하는가?
-> 가능하면 정적 메모리를 활용하자. (속도도 빠르고 메모리도 알아서 정리해주니 편하다.)
정적 메모리에 넣기에는 너무 크거나
들어올 수 있는 크기의 변동 폭이 너무 커서 메모리 크기를 예측하기 어려울 때 사용하자.
* 언제 해제하는가?
-> 가능하면 할당한 함수 안에서 해제한다.
(return 조건이 많아서 헷갈린다면 goto문을 사용해 함수 맨 아래에 free()를 넣으면 해제가 명확하다.)
-> 함수가 동적 메모리는 반환한다면 함수명이나 변수명에서 동적 메모리임을 명확하게 표시하자.
예제
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int main()
{
char* p = malloc(sizeof(char) * 3);
char* pp = p;
*pp++ = 'a';
*pp++ = 'b';
*pp = '\0';
printf("주소값: %p\n", p);
printf("%s", p);
free(p);
}
* 할당받은 포인터 자체를 가지고 사용하는 건 바뀔 수 있으므로 위험하다. (해제할 때 필요하기 때문에)
다른 포인터를 만들어서 사용하면 좀 더 나은 방법?
void* calloc(size_t count, size_t size);
매개변수(인자)
size_t count
size_t size
두 개의 매개변수의 차이가 아예 없다...
반환값(리턴값)
* 주소를 반환한다. (void*)
실패 시 NULL
설명
* (count * size)만큼의 바이트를 스택에서 할당받는다.
매개변수 2개의 순서를 혼동해도 전혀 상관이 없다.
* 특징. 할당받은 메모리를 0으로 초기화해준다. (편할 수도 있고, 성능 저하일 수도 있다.)
귀여운 그림은 낡은 창고님이 그리셨습니다.