정적 메모리를 우선적으로 사용하는 것이 무조건 좋다 안될 때만 동적 메모리 사용하자
동적 메모리의 소유주
메모리를 생성한 함수에서 메모리를 해제하자
return
해버리면 ..?소유주가 아니라면 메모리를 해제하지말 것
힙 메모리 관리자에게 xxx 바이트만큼 달라고 요청
관리자는 연속된 메모리 찾아서 반환 (메모리주소형태 : 포인터로 저장가능)
void* malloc(size_t size);
size
바이트 만큼의 메모리를 반환해줌
초기화 안해준다 (처음 들어있는 값은 쓰레기값)
메모리가 없거나 실패하면 NULL
반환
반드시 free()
와 함께 사용!!!
#include <stdlib.h>
size_t i;
int* nums = malloc(10 * sizeof(int)); // 10 * 4 : 40byte할당 해주세요
for (i = 0; i < 10; i++){
nums[i] = i * 10;
}
free(nums) // 다 사용했으니 해제해주세요
void* realloc(void* ptr, size_t new_size)
이미 존재하는 메모리의 크기를 new_size크기로 변경
실패시 NULL
을 반환하지만 기존 메모리는 해제되지 않음
기존 주소를 잃어버려서 메모리 누수가 생길 수 있다.
void* nums;
nums = malloc(size);
nums = realloc(nums, 2 * size); // 실패하면 nums의 원래주소를 알 수가 없다..
올바른 재할당 방법은 임시변수를 사용해서 주소 받아와서 저장
크기가 커지는 경우 (크기가 작아지는 경우도 비슷)
void* memset(void* dest, int ch, size_t count);
dest 위치부터 count 바이트만큼 ch 값으로 초기화 해주라
<string.h>
에 있음
char
로 초기화 됨 (1바이트씩)
// char형으로 잘못 초기화 된 예
void* nums;
nums = malloc(4 * sizeof(int));
memset(nums, 1000, 4 * sizeof(int)); // int 1000은 16진수로 = 00 00 03 E8 -> 실제로 E8만 저장
free(nums);
nums = NULL;
// int형으로 직접 초기화
p = nums;
for (i = 0; i<4; i++){
*p++ = 1000;
}
free(nums);
nums = NULL;
count가 dest의 영역을 넘어설 경우, dest가 널 포인터일 경우 문제가 발생할 수 있다.
void* memcpy(void* dest, const void* src, size_t count);
<string.h>
에 있음int memcmp(const void* lhs, const void* rhs, size_t count);
strcmp()
와 매우 비슷void free(void* ptr)
할당받은 메모리를 해제하는 함수 (메모리 할당 함수를 통해 받은 메모리만 해제 가능)
함수에서 메모리 할당 후 까먹고 해제안했는데 함수가 반환된 상태라면...?
문제가 될 수 있는 경우
int* nums;
nums = malloc(LENGTH * sizeof(int));
for (i = 0; i < LENGTH; i++){
*nums++ = 10 * (i + 1); // nums가 최초로 할당받은 주소가 아닌 다른 주소를 가리킴
}
free(nums); // 다른 주소를 해제해버림..
실수를 줄이는 방법
해제한 메모리를 누군가 다시 사용하면?
free()호출 이후 널포인터를 대입해준다.
free(nums);
nums = NULL;
free는 몇 바이트를 해제할지 어떻게 알지?