Mandatory Part
Prototype
int get_next_line(int fd, char **line);
Return Value :
1 : A line has been read
0 : EOF has been reached
-1 : An error happened
file descriptor로부터 파일을 읽어 줄 단위로 가져온다. 단 개행문자 \n은 제외하고 가져온다.
반복문 내에서 get_next_line 함수를 호출하면 fd의 텍스트를 한 번에 한 줄씩 EOF가 나올 때 까지 읽는다.
FILE로부터, Standard input으로부터, redirection으로부터 텍스트를 잘 읽어와야한다.
BUFFER_SIZE 가 9999일 때, 1일 때, 10,000,000일때 작동 되는가? 이유도 아는가?
한 번 실행할 때 마다 한 줄 씩만 읽어야한다. newline을 만나면, 현재 line을 반환해야한다. 한 번에 모든 파일을 읽어온다음 처리하지 말자.
Standard Output 에 newline을 보내거나, CTRL-D를 보내면 어떻게 되는가?
CTRL-D는 EOF이다.
Bonus Part
size_t read(int fd, void *buf, size_t bytes);
#include <fcntl.h>
int open (const char *FILENAME, int FLAGS[, mode_t MODE])
참고
외부에서 #define을 정의한다.
이 문제에서 컴파일은 다음과 같이 진행된다.
$ gcc -Wall -Wextra -Werror -D BUFFER_SIZE=32 get_next_line.c get_next_line_utils.c
즉, BUFFER_SIZE를 컴파일할 때 정하게 된다.
지역 / 전역 변수의 값을 기억해 두고 싶을 때 사용한다.
⚠ get_next_line()을 호출할 때 이전에 읽은 값 중 일부는 기억하고 있어야 하기에, 정적 변수에 기억해야 할 값들을 넣어둬서 다음 호출에 대비한다.
데이터 영역에 저장되어 프로그램 종료 시 까지 남아있기 때문에, 다음 line을 읽을 시작 주소을 계속 저장할 수 있도록 backup 버퍼를 static 변수로 선언해야 한다.
static 자료형 변수이름
#include <stdio.h>
#include "get_next_line.h"
char *accu_bufs(char *str) {
static char *backup = "";
char *new_backup;
// new_backup의 길이를 구하기
size_t new_backup_len = ft_strlen(backup) + ft_strlen(str);
if (!(new_backup = (char *)malloc(sizeof(char) * (new_backup_len + 1))))
return (NULL);
// new_backup에 backup 값과 새로운 값 복사
size_t idx = ft_strlcpy(new_backup, backup, new_backup_len + 1);
ft_strlcpy(new_backup + idx, str, new_backup_len + 1);
// backup이 new_backup을 가리키도록 설정
if (ft_strlen(backup) != 0)
free(backup);
backup = new_backup;
return (backup);
}
int main(void) {
printf("%s\n", accu_bufs("Hello 42"));
printf("%s\n", accu_bufs(" world, "));
printf("%s\n", accu_bufs("hao!"));
return (0);
}
// 실행 결과
// Hello 42
// Hello 42 world,
// Hello 42 world, hao!
변수
지역 변수 : 스택에 들어가는 변수
= 일반 변수
전역 변수 : 스택에 들어가지 않는 변수
= static 전역 변수 + heap 전역 변수
메모리 공간 = 코드 영역 + 데이터 영역 ( heap + stack )
처음부터 모든 메모리 공간을 사용하는 것은 아니고, 보통 힙과 스택 사이가 비어있다. 이들은
(1) 스택이라면 함수가 호출될 때
(2) 힙이라면 동적으로 할당했을 때
할당된다.
그렇다면 힙과 스택은 최대 얼마까지 할당할 수 있을까?
힙과 스택은 기본적으로 사용자 지정에 의해 최대 크기를 정할 수 있지만 하드웨어는 유한하기 때문에 할당 가능한 최대 크기도 유한하다. 스택과 힙은 남은 램의 크기만큼 할당할 수 있다.
코드에서 설정한 스택 사이즈를 오버하는 큰 메모리를 스택에 할당하면(called Stack Over Flow) "Segmentation fault"와 함께 프로그램이 죽은 것을 확인할 수 있으니, 그 때는 힙 메모리를 활용해라.
stack size를 확인하는 리눅스 명령어
>ulimit -a
1234\n123\n이고 버퍼사이즈가 20일때
첫번째 gnl에서 read가 끝까지 다 읽어서
두번째 gnl을 호출했을때는 read가 0을 뱉는 것으로 알고있습니다
첫번째 gnl에서 1234가 출력되고 save에 123\n이 저장 되어 있어서
두번째 gnl에서 123을 출력하려면 save안에서 개행문자를 찾아줘야 되는것으로 알고있습니다