혹시나 문제가 된다면 바로 비공개 처리하겠습니다. 지적이나 댓글 환영합니다!
이번 포스팅에서는 malloc을 사용한 함수 2개 (calloc, strdup)를 구현해보겠다.
malloc을 통해 동적할당을 할 수 있고, 이를 통해 메모리를 더욱 유연하고 자유롭게 쓸 수 있다.
참고로, 내가 정의한 libft.h 헤더에는 <unistd.h>와 <stdlib.h>가 include 되어있다. 따라서 libft.h를 호출하면, 따로 정의하지 않고도 <unistd.h> 에 정의된 size_t 타입과 <stdlib.h>의 malloc/free를 사용할 수 있다.
(1) calloc : 0으로 초기화된 메모리를 할당
- 매뉴얼(영문번역) :
이름 : calloc -- 메모리 할당
시놉시스 :
#include <stdlib.h>
void *calloc(size_t count, size_t size);
설명 :
calloc() 함수는 메모리를 할당한다. 할당된 메모리는 그것이 어느 데이터 타입이든 쓸 수 있게 정렬된다.
(이때 타입은 AltiVec-와 SSE-관련 타입들을 포함한다)
free() 함수를 통해 이러한 메모리 할당 함수로 할당된 메모리를 해제할 수 있다.
calloc() 함수는 size로 주어진 바이트의 메모리를 가진 count 개수의 객체들을 위한 충분한 공간을
연속적으로 할당한다. 그리고 할당된 메모리의 포인터를 반환한다.
할당된 메모리들은 0값을 가진 바이트들로 채워진다
리턴값 : 성공할 경우, 할당된 메모리의 포인터를 반환한다.
만일 오류가 발생한다면, NULL 포인터를 반환한 후 errno를 ENOMEM으로 설정한다.
- 구현 코드 예시 :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#include "libft.h"
void *ft_calloc(size_t count, size_t size)
{
size_t i;
unsigned char *ptr;
if (!(ptr = malloc(size * count)))
return (0);
i = 0;
while (i < size * count)
{
ptr[i] = 0;
i++;
}
return ((void *)ptr);
}
|
cs |
- malloc을 통해 size * count만큼 메모리를 할당해주었다
- ptr 이 null(0)일 경우, 메모리 할당이 실패했으므로 ptr을 반환하여 null 포인터를 반환한다.
- 성공적으로 메모리를 할당한 경우, size * count 만큼의 메모리 영역에 unsigned char 형의 포인터를 통해 1바이트씩 접근한다. 그리고 매번 0을 할당하여 할당한 메모리 영역을 모두 0으로 초기화한다
- 메모리 초기화까지 성공하면 (unsigned char *) 형의 ptr을 (void *)로 형변환하여 리턴해준다.
- 참고) errno를 ENOMEM으로 설정한다는 것의 의미
errno는 에러가 발생할 때 마다 기록을 저장하고 있는 전역변수이다.
errno 전역 변수는 프로그램이 시작할 때 "에러가 발생하지 않았다"는 뜻의 0으로 시작해서, 에러가 발생할 때마다 새로운 에러 번호로 갱신된다. (매번 갱신되는 것이 아니라 에러 발생 시 마다 갱신)
ENOMEM : not enough memory (kernel이 사용할 수 있는 메모리 부족)
- 주의) malloc() 실패 시의 널가드를 뺴먹지 말아야한다 (이걸로 동료평가 디팬스 실패했었음)
실제 라이브러리의 calloc()을 호출하여 결과를 확인한 경우, size * count 가 메모리 주소 범위를 벗어날 경우, 메모리 주소로 0이 들어가는 결과가 출력된다.
이를 유의하여 동일하게 구현할 수 있도록 주의해야한다.
(2) strdup : 메모리 할당 및 문자열 복사
- 매뉴얼(영문번역) :
이름 : strdup -- 문자열의 사본을 저장
라이브러리 : 표준 C 라이브러리 (libc, -lc)
시놉시스 :
#include <string.h>
char *strdup(const char *s1);
설명 :
strdup() 함수는 문자열 s1의 사본을 저장하기 위한 충분한 메모리를 할당한다. 그리고 복사를 수행한다.
그리고 그것에 대한 포인터를 반환한다. 해당 포인터는 그 후에 free()의 인자로 사용될 수 있다.
할당할 수 있는 메모리가 불충분할 경우, NULL이 반환되며, errno가 ENOMEM으로 설정된다.
리턴값 : 성공할 경우, 할당된 메모리의 포인터를 반환한다.
만일 오류가 발생한다면, NULL 포인터를 반환한 후 errno를 ENOMEM으로 설정한다.
- 구현 코드 예시 :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
#include "libft.h"
char *ft_strdup(const char *s1)
{
char *ptr;
size_t len;
size_t i;
i = 0;
len = ft_strlen(s1);
ptr = malloc(sizeof(char) * (len + 1));
if (!(ptr))
return (0);
while (i < len)
{
ptr[i] = s1[i];
i++;
}
ptr[i] = '\0';
return (ptr);
}
|
cs |
- 우선 주어진 문자열의 길이 + 1 만큼 공간을 할당해 주었다.
- ptr에 동적할당이 실패한 경우 (하드웨어의 여유 메모리 부족 등 여러가지 원인), null을 반환한다.
- 동적할당 된 포인터에 주어진 문자열을 복사한 후, 끝에 null을 넣고 해당 포인터를 리턴한다.
- 문자열의 길이값을 size_t 형의 변수 len으로 받았기 때문에, while 문의 조건식에서 len과 비교해야하는 인덱스 변수 i 또한 size_t로 선언해주었다.
참고 자료 출처 :
'IT > 42Seoul' 카테고리의 다른 글
[Libft] C 언어 라이브러리 구현_Part2_추가함수 구현1 (0) | 2021.05.23 |
---|---|
42서울 : 라피신 후기 + 본과정 합격 후기 (4기 2차 : 3 /22 ~ 4/16) (0) | 2021.05.20 |
[Libft] C 언어 라이브러리 구현_Part1_문자 판별 + 변환 관련 함수 (0) | 2021.05.20 |
[Libft] C 언어 라이브러리 구현_Part1_문자열 관련 함수 (0) | 2021.05.20 |
[Libft] C 언어 라이브러리 구현_Part1_mem관련 함수 (0) | 2021.05.17 |