과제 내용
이전 libft 과제의 후반부에서 fd 이름이 붙었던 함수들을 만들면서 공부하게 된 '파일디스크립터'
그 '파일디스크립터'를 통해서 특정 사이즈만큼 파일로부터 내용을 읽어들이는 'read'라는 함수를 사용하여
문장단위로 내용을 반환하는 것입니다
여기서 문장은 '개행'을 기준으로 나누어진 문자열이라고 생각했습니다
여러 줄이 있으면 줄 수만큼 문장이라고 할 수 있고 딸랑 한 줄로 끝나도 문장이라고 할 수 있겠네요
하지만 과제 pdf를 유심히 살펴보면 우리에게 주어지는 buffer size에 특정 값들을 넣었을 때
제대로 작동되는지 두 번이나 물어보는 문구를 발견할 수 있습니다
전 이 부분이 궁금해서 직접 해당 buffer size를 넣어보며 실행해 봤고 서로 다른 결과를 보며
왜 이러한 결과가 나타나는지 궁금해서 열심히 구글링을 해보았고
그 결과...
단순 파일 내용 출력 과제라고 생각했었으나 갑작스럽게 cs 지식을 얻게 되었습니다
이전까지는 malloc을 사용한 동적 할당만 알고 있었으나 이 과제에서 추가적으로
static 키워드를 통해 메모리에 데이터를 할당하는 방법을 공부하게 됩니다
착각했던 부분
1.
위의 내용과 연결되는 부분이 있습니다
저는 bonus를 진행할 때 linked list를 구현하여 해결하였는데
static 키워드를 통해 malloc 함수가 아닌 다른 방법으로 메모리에 할당을 해주지만
여전히 malloc 에 익숙해져있다 보니 이 데이터들이 어떤 구조로 메모리에 올라가있고
서로 어떤 식으로 참조하면서 연결되어 있는지 머릿속에서 잘 그려지지 않았습니다
그렇다 보니 'list의 헤더를 담당하는 부분은 static 때문에 함수가 종료되어도 남아있는 건 알겠는데
나머지 노드들은 static이 아닌데도 어떻게 함수가 종료되어도 남아있는거지??' 라는 바보 같은 생각과 함께
자기가 만들어놓고도 자기가 이해를 못 하는 상황에 빠져있었지만
static 변수에 관한 자료를 다시 한번 천천히 훑어보면서 착각을 풀어나갔습니다
2.
다중 fd에 대응해야 하는 bonus 과제에서
get next line이 오류가 난 경우 그동안 만들었던 fd 정보를 담은 구조체를
전부다 날려버릴 것인지 아니면 오류가 난 fd 정보를 담은 구조체만 날려버릴 것인지도 고민했고
이건 구글링해도 나올 리 없으니 다른 카뎃분들과 이야기를 해서 후자를 선택했습니다
어느 방식을 선택하던 테스터기에서는 OK가 출력되지만
결국 내가 나의 프로그램을 만들어나가는 과정에서
특정 상황에 의미 부여를 하고 이런 상황에서는 이런 식으로 동작하도록
내가 직접 '행동에 정의를 내리는' 것을 연습하는 것이 중요하다고 생각했습니다
전 둘 중에 하나만 정답이라고 생각하지는 않습니다
하지만 선택을 했다면 왜 그렇게 생각했는지와 유저가 어떤 식으로 사용할지에 대한 예상
그리고 이전까지 공부했던 내용 중에 'undefined behavior'라는 키워드가 왜 존재는 지에 대해서
고민해 보면 이런 부분도 재미있다고 생각합니다
3.
'문장이 하나 이상 존재할 경우 개행까지 읽어오는 것'과 '문장이 하나뿐일 경우 마지막까지 읽어오는 것'에서
문장까지의 구분문자를 확인하기 위해 기존의 libft에서 문자열에서 문자를 찾는 함수를 가져다가 썼습니다
그리고 해당 함수를 위의 두 가지 상황에 각각 한 번씩 총 두 번을 호출하였는데
이 부분을 norminette의 25자 제한에 맞춰 수정해야 할 때 굉장히 곤란했었습니다
원래 해당 함수에서 찾을 문자를 인자로 받는 부분이 있었는데
처음에는 여기서 flag라는 인자를 하나 더 주고 flag에 따라 문자'A'와 문자'B'를 찾는 식으로 작성했었으나
스터디의 다른 분의 코드를 참고하고 나서 해당 함수 내부에 있는
'while 조건문으로 무언가를 탐색한다'의 의미를 다시 한번 생각해 보게 되었습니다
그리하여 함수 호출을 하지 않고 조건문 하나로 두 가지 상황에 모두 대응할 수 있도록 수정했습니다
힘들었던 부분
단연코 에러 핸들링 부분이라고 말할 수 있다고 생각합니다
이전까지 단일 함수를 구현하는 과정에서는 에러가 발생할 경우
즉시 프로그램을 종료해버리면 목표를 달성하는 것이었지만
이번 과제에서는 단일 함수에서 끝나는 것이 아니라 여러 함수들을 타고 타고 들어가기 때문에
도중에 에러가 발생하면 계속 밖으로 빠져나오면서 최종적으로 get next line 함수에서
프로그램을 종료하도록 해야 합니다
마치 이전까지는 에러가 발생하는 즉시 '나 이제 그만할래' 하고 내팽개쳐도 문제가 없었다면
이번에는 에러가 발생할 경우 에러 값을 바구니에 담은 채 흘리지 않게 출발선까지 되돌아가는 느낌이네요
이를 통해서 '이 함수에서만 할 수 있는 행동'과 '다른 함수에도 할 수 있는 행동'을 구분 지어서 생각하게 되었고
이것을 토대로 함수들의 역할을 다시 수정해 보는 재미가 있었....재미없었습니다
많이 어려웠어요 머리도 뜨겁고...
그래도 이전과는 다르게 여러 함수를 구성하여 무언가를 만드니 진짜 프로그램 같은 느낌이 들기 시작했습니다
작업은 각각의 함수에서 알아서 처리하지만 그 결괏값은 모두 같은 곳으로 빠져나와서 다른 변수에 넣어주거나
혹은 다른 함수를 이용해서 작업 방향을 변경하거나 프로그램을 종료해버리는 등
마치 도로가 연상되기도 했습니다
자주 만났던 문제들
스터디 팀원분들과 공유해봤던 문제들 중에 자주 볼 수 있었던 문제들은 아래와 같습니다
1.
문자열을 while 조건문에 넣었을때 'Segmentation Fault'가 발생하는 경우
while 조건문에서 문자들을 하나씩 출력해봤더니 맨 마지막의 null 문자가 사라진 경우
*힌트*
malloc 사이즈를 잘못 측정한 경우가 대다수였습니다
2.
메모리 누수 부분
쉽게 생각했지만 의외의 복병이 숨어있습니다
*힌트*
위에서 말한 '메모리에 값을 할당하는 방법들' 을 보고 각 방법별로 내가 해제를 빼먹지 않았나 체크해보면 빠르게 찾아 낼 수 있습니다