[42 Seoul] get_next_line

한종민·2023년 4월 19일
0

42SEOUL

목록 보기
3/6

get_next_line


정적 변수 (Static Variable)

  • 지역 변수의 특성과 전역 변수의 특성을 합친 변수
  • 특정 함수에만 사용 가능하면서도 함수가 끝나더라도 값이 그대로 유지됨
  • 다라서 프로그램이 끝날 때까지 변수 안의 값이 유지됨
  • 모든 전역 변수들은 정적 변수라고 할 수 있다.
  • 컴파일 시간에 데이터 영역에 메모리를 할당하여 저장되며 프로그램이 끝나면 자동 삭제됨
  • 초기 값을 지정하지 않는다면 0으로 자동으로 초기화된다.

댕글링 포인터

포인터가 여전히 해제된 메모리 영역을 가르키고 있다면 이러한 포인터를 댕글링 포인터라고 한다. 댕글링 포인터가 가리키는 메모리는 더는 유효하지 않다. 댕글링 포인터는 조숙한 해제, 너무 급한 해제라고 부르기도 한다.

댕글링 포인터의 사용은 아래 목록에 나열된 문제를 포함한 다양한 문제를 야기한다.

free 함수로 메모리를 해제한 후에도 변수는 여전히 메모리의 주소를 가리고 있다. 이 메모리는 힙관리자에 의해 재사용되거나 기존의 정수가 아닌 다른 타입으로도 사용될 수 있다. free 함수를 호출하면 원래 pi 포인터가 가리키고 있던 주소에 위치한 메모리는 해제되며 다시 사용할 수 없다. 그러나 대부분의 런타임 시스템에서 해제 뒤에 발생하는 메모리의 접근이나 변경을 막지 않는다.

만약 버퍼사이즈가 스택의 저장공간보다 크게 입력된다면?

BUFFER_SIZE가 스택의 저장공간보다 크게 입력되어 들어온다면 Segmentation fault 오류가 발생될 것이다.

스택의 저장공간의 사이즈는 운영체제마다 상이하다.

OPEN_MAX

open_max를 사용하게 될 경우의 문제점

  • 값이 항상 운영체제에서 설정된 fd 값과 같다는 보장이 없다.
  • open_max값보다 큰 갯수의 파일을 열려고 할 경우 해당 함수는 오류를 발생할 것이다.

코드 정리

  • static 문자열인 backup이 만약에 없다면 ft_strdup를 통해 “” 빈 문자열을 할당해 준다.
  • 이 backup문자열에 ‘\n’ 이 존재할 때까지 반복되는 while문을 만든다.
  • readed 변수로 read()함수의 리턴 값을 받고, 이 리턴 값이 -1이 거나 0이면서 backup이 존재하지 않는 경우 return (0);
  • 버퍼의 마지막 readed 인덱스에 ‘\0’ 삽입
  • readed가 0인데, backup이 아직 남아있다면, 파일의 마지막에서 읽을 버퍼는 없지만 출력해야할 문장이 backup에 남아있으므로, ft_add() 함수로 들어 가지않고, 바로 출력할 수 있게끔, break해준다.
  • 위의 경우가 아니라면 backup과 buf를 가지고 그 두 문자열을 join해주는 ft_add () 함수로 보낸다.
  • ft_add() 함수에서 backup과 buf를 join해주고 다 사용한 backup은 free() 해준다.
  • 이렇게 join해서 만들어진 문자열을 다시 backup문자열에 담아 주고, 만약 이 backup문자열에 ‘\n’이 포함되어 있다면 반복문에서 빠져나오게 된다.
  • 반복문에서 빠져나와 ft_cut 함수로 ‘\n’이 포함된 backup문자열을 가지고 가게된다.
  • ft_cut함수의 기능은 ‘\n’을 기준으로 앞의 문자열은 ret_read문자열에 substr로 복사해서 할당해준다.
    ’\n’을 기준으로 뒤의 문자열은 backup에 새로 할당 해준다. 이전 backup은 tmp에 복사해두었다가 재할당이 끝난 뒤, tmp를 free해주는 것으로 해결한다.
  • 리턴값을 gnl이 출력해야할 ‘\n’을 포함한 ret_read를 리턴한다.

내가 만든 코드!

#include "get_next_line.h"
#include <stdio.h>

char	*ft_substr(char *s, unsigned int start, size_t len)
{
	char	*substr;
	size_t	s_len;
	size_t	i;

	s_len = ft_strlen(s);
	if (s_len <= start)
	{
		substr = (char *)malloc(sizeof(char));
		if (!substr)
			return (NULL);
		substr[0] = '\0';
		return (substr);
	}
	if (s_len - start < len)
		len = s_len - start;
	substr = (char *)malloc(len + 1);
	if (!substr)
		return (0);
	i = -1;
	while (++i < len)
		substr[i] = s[start++];
	substr[i] = '\0';
	return (substr);
}

// static char	*ft_add(char **backup, char *buf)
// {
// 	char	*tmp;

// 	tmp = ft_strjoin(*backup, buf);
// 	if (!tmp)
// 		return (0);
// 	*backup = tmp;
// 	free(tmp);
// 	tmp = NULL;
// 	return (0);
// }

// static char	*ft_add(char **backup, char *buf)
// {
// 	char	*tmp;

// 	tmp = *backup;
// 	*backup = ft_strjoin(tmp, buf);
// 	if (!(*backup))
// 	{
// 		free(tmp);
// 		return (0);
// 	}
// 	free(tmp);
// 	return (0);
// }

static char	*ft_add(char *backup, char *buf)
{
	char	*tmp;

	tmp = ft_strjoin(backup, buf);
	if (!tmp)
	{
		free(backup);
		return (0);
	}
	free(backup);
	return (tmp);
}

static char	*ft_cut(char **backup)
{
	char	*tmp;
	char	*ret_read;
	int		i;

	i = ft_strchr_index(*backup, '\n');
	if (i == -1)
		i = ft_strchr_index(*backup, '\0');
	ret_read = ft_substr(*backup, 0, i + 1);
	if (!ret_read)
	{
		free(*backup);
		*backup = NULL;
		return (0);
	}
	tmp = *backup;
	*backup = ft_substr(*backup, i + 1, ft_strlen(*backup));
	if (!tmp)
	{	
		free(*backup);
		*backup = NULL;
		return (0);
	}
	free(tmp);
	return (ret_read);
}

int	read_check(int read, char **backup)
{
	if (read == -1 || (read == 0 && !(**backup)))
	{
		free(*backup);
		*backup = NULL;
		return (1);
	}
	return (0);
}

char	*get_next_line(int fd)
{
	static char	*backup;
	char		buf[BUFFER_SIZE + 1];
	int			readed;

	if (!backup)
		backup = ft_strdup("");
	if (!backup)
		return (0);
	while (ft_strchr_index(backup, '\n') < 0)
	{
		readed = read(fd, buf, BUFFER_SIZE);
		if (read_check(readed, &backup))
		{
			free(backup);
			backup = NULL;
			return (0);
		}
		buf[readed] = '\0';
		if (readed == 0 && (*backup))
			break ;
		backup = ft_add(backup, buf);
		if (!backup)
			return (0);
	}
	return (ft_cut(&backup));
}

// #include <stdio.h>

// int main(void)
// {	
// 	int		fd;
// 	char	*line;

// 	fd = 0;
// 	fd = open("./test",O_RDONLY);
// 	line = get_next_line(fd);
// 	printf("|%s|", line);
// 	line = get_next_line(fd);
// 	printf("|%s|", line);
// 	line = get_next_line(fd);
// 	printf("|%s|", line);
// 	line = get_next_line(fd);
// 	printf("|%s|", line);
// 	line = get_next_line(fd);
// 	printf("|%s|", line);
// 	line = get_next_line(fd);
// 	printf("|%s|", line);
// 	line = get_next_line(fd);
// 	printf("|%s|", line);
// 	return (0);
// }
profile
내가? 이것도?

0개의 댓글