운영체제 - Memory API

혀누·2024년 1월 4일
0

운영체제

목록 보기
9/10
post-thumbnail
post-custom-banner

Malloc()

  • Heap에 memory 공간을 할당하기 위해 사용하는 API
#include <stdlib.h>
void* malloc(size_t size)
  • size_t : unsigned integer type (typedef)
  • size_t size : size of memory block (bytes)
  • memory allocation에 성공하면 memory의 시작 주소값을 return, 실패하면 NULL을 return

Calloc()

#include <stdlib.h>
void *calloc(size_t num, size_t size)
  • malloc과 달리 0으로 초기화해주기 때문에 느리다. 초기화가 중요하지 않으면 malloc 권장

Sizeof()

  • sizeof()는 함수가 아니라 연산자이다. compile-time에 연산되어 결과가 return된다.
    따라서 아래 예시처럼 2가지 결과를 도출하게 된다.
int *x = malloc(10 * sizeof(int));
printf(%d\n”, sizeof(x));

4

int x[10];
printf(%d\n”, sizeof(x));

40

위에선 x를 동적할당하고 있기 때문에 40byte가 run-time에 할당된다. 따라서 sizeof(x)의 결과는 단순히 pointer변수의 크기인 4byte가 출력된다.
아래에서는 x를 정적할당하였기 때문에 40byte가 compile-time에 할당된다. 따라서 40이 출력된다.

Free()

  • malloc()으로 할당한 memory 공간을 해제하는 API
#include <stdlib.h>
void free(void* ptr)
  • free는 memory 공간의 시작주소 밖에 모르는데 어떻게 memory를 해제할 수 있을까?
    -> malloc으로 memory를 할당할 때 8byte의 추가공간을 할당해 memory의 크기 정보를 저장하고
    free할 때 이 정보를 이용하여 해제한다.


    위와 같이 free를 하더라도 포인터 변수 pi에 저장된 값이 사라지는 것은 아니다.

Forgetting To Allocate Memory

char *src = “hello”; //character string constant 
char *dst; //unallocated
strcpy(dst, src); //segfault and die

위의 코드에서 문자열 상수인 "Hello"는 code 영역에 할당된다.
dst에는 쓰레기값이 들어있고 그 위치는 할당된 공간이 아니기 때문에 strcpy에서 segfault error가 생긴다.

char *src = “hello”; //character string constant 
char *dst = (char *)malloc(strlen(src) + 1); //allocated
strcpy(dst, src); //work properly

따라서 dst를 선언하면서 src의 크기만큼 memory를 할당해주면 해결된다.

Not Allocating Enough Memory

char *src = “hello”; //character string constant 
char *dst (char *)malloc(strlen(src)); // too small
strcpy(dst, src); //work properly

strcpy는 src에서 NULL문자가 등장할 때까지 순차적으로 복사한다.
위의 코드에서는 dst가 src의 크기보다 1byte 작게 할당되었기 때문에 NULL문자는 할당되지 않는 공간에 복사되는 문제가 생긴다. 그러나 아래 2가지 이유로 위의 코드는 정상적으로 작동할 것이다.
1. 사실 malloc으로 공간할당을 할 때 주어진 size보다 크게 할당하기 때문에 segfault가 발생하지 않는다.
2. NULL문자가 복사되는 공간이 우연히 다른 malloc 함수에 의해 할당된 공간일 수도 있다.

Forgetting to initialize

int *x = (int *)malloc(sizeof(int)); // allocated
int *y = (int *)malloc(sizeof(int) * 200); // allocated
// *x = 4;
// memset(y, 0, sizeof(int) * 200)
printf(*x = %d\n”, *x); // uninitialized memory access

초기화를 해주지 않아 쓰레기값이 출력된다.
초기화 방법으로 위의 주석처리된 2가지 방법이 있다.
x처럼 간단한 경우를 제외하고 memset이라는 함수를 사용할 수 있는데
memset의 첫 번째 인자는 주소값, 두 번째 인자는 초기화하려는 값, 마지막 인자는 memory size이다.

Memory Leak

  • free(해제)하지 않았지만 더 이상 사용하지 않는 memory

    unused한 memory가 증가하면 memory 초과문제가 발생할 수 있다.

Dangling Pointer

  • free(해제)한 memory를 가리키는 pointer

Double Free

  • 이미 free한 memory를 한 번 더 free
int *x = (int *)malloc(sizeof(int)); // allocated
free(x); // free memory
free(x); // free repeatedly

System calls

#include <unistd.h>
int brk(void *addr)
void *sbrk(intptr_t increment);
  • brk : end of the heap (break)를 addr로 이동시켜 heap 영역을 확장시킨다.
  • sbrok : increment만큼 break를 이동시켜 heap 영역을 확장시킨다.
  • programmer가 직접 호출해서는 안 된다.
profile
정리용 블로그
post-custom-banner

0개의 댓글