메모리를 언제 해지시켜주느냐 하는 질문 입니다.
글쓴이: song / 작성시간: 금, 2003/06/27 - 3:11오후
메모리를 언제 해지시켜주느냐 하는 질문 입니다.
문자열을 token해주는 함수 입니다.
함수 원형은 : char ** tokenize(const char *string, const char *delim, int *n)
인자는 차례대로 문자열, 구분자, 담겨진 개수 이런식입니다.
int spit;
char **tmp;
char get_int[2];
tmp = tokenize(parv[parc - 1],get_int, &spit); //메모리 할당. spit는 배열의 크기입니다.
if(!strncmp(tmp[0],"ADD",ITOA_BUF_LENGTH))
m_group_add(tmp,spit);
else if(!strncmp(tmp[0],"DEL",ITOA_BUF_LENGTH))
m_group_del(tmp,spit);
free_string_array(tmp,spit); //메모리 해지.
아스키 4번을 구분자로 해서 문자를 잘라 첫번째를 명령어로 인식해서 해당 명령어의 함수를 호출하는 코드 입니다.
tokenize함수안에는 메모리를 할당 하고 있습니다.
문제는 위와같은 방법으로는 메모리 해지가 안되는거 같습니다.
매모리 해지를 m_group_add 함수 안에서 해줘야 하는것인지요 아니면
위와 같은 방법으로 메모리 해지를 해주는것인지요.
Forums:
질문의 답은 아닙니다만...
한마디 코멘트하자면요...
표준 라이브러리에서 제공하는 기능을
굳이 손수 구현하려고 하는 것은 바람직하지 않습니다.
표준 라이브러리는 사실상 언어의 일부이고, 독립적으로 생각하면 안됩니다.
표준에서 제공하는 기능을 사용하는 것이 구현하기도 쉬울 뿐만 아니라,
다른 사람이 코드를 읽을 때도 쉽게 이해할 수 있습니다.
보통 표준에서 제공하는 기능보다 우수한 코드를 개발자 혼자서 만드는 것은 매우 어렵습니다. 표준 라이브러리는 상당히 오랜시간 동안 수많은 고수들의 손을 거쳐서 만들어진 겁니다.
그러므로 님의 tokenize() 대신, ANSI C의 strtok()이나 POSIX 표준의 strtok_r() 함수를 이용하시기 바랍니다.
왜 표준에서는 님과 같은 식으로 토크나이징을 구현하지 않았는지를 생각해보시길 바랍니다.
표준 함수에서는 메모리를 함수 자체에서 할당해서 리턴하는 경우는 없습니다.
메모리 할당/해제는 항상 malloc/free (또는 new/delete)로만 하고,
함수에서는 할당된 메모리를 읽어서 작업하는 방식으로 해야 합니다.
필요하다면 glibc에 있는 소스 코드를 참고하는 것도 도움이 될 겁니다.
정 표준에서 제공하는 기능이 마음에 들지 않는다면, 새로 만드는 것보다 이 소스 코드를 바탕으로 하여 만드는 것이 좋습니다.
(strtok_r이 바로 그렇게 하여 만들어진 산물입니다. thread-safe한 특징이 있죠.)
cedar 님께 질문
전부터 궁금하던건데
glibc 에서 제공하는 함수 중에서
내부에서 메모리를 할당해서
사용하는 측에서 해제시켜 주어야 하는 함수는
전혀 없나요?
전혀?
개념없는 초딩들은 좋은 말로 할때 DC나 웃대가서 놀아라. 응?
Re: 질문의 답은 아닙니다만...
이것은 사실이 아닙니다. 대표적인 예로는, libc 가운데 strdup 가 있습니다.
이것 역시 관점에 따라 다를 수 있습니다. standard implementation 이라는
것이 portability, performence 등의 고려가 robustness 보다 앞서기 때문에
상당히 위험한 함수가 많습니다. string.h 에 있는 대부분의 함수들은 적절히
wrapper 를 만들어서 사용하는 것이 안전합니다. string 관련 함수들은 대부분
target string 의 size 는 고려하지 않고, NULL character에 의존하여
boundary check 를 하기 때문입니다. strcpy 같은 함수는 상당히 위험한 함수
로 잘 알려져 있죠, 경우에 따라 strlen 같은 경우도 위험하기 이를데 없습니다.
Let it be...
[quote]표준 함수에서는 메모리를 함수 자체에서 할당해서 리턴하는
getcwd 도 첫번째 인자가 NULL 인경우 할당해서 리턴합니다.
이중포인터 자체의 메모리도 해지되어야 하는듯 합니다.char **
이중포인터 자체의 메모리도 해지되어야 하는듯 합니다.
char **s_Temp;
여기에 그와 같은 함수로 토큰을 분리했을때
만약 토큰수가 3개라면 다음과 같이 메모리에 할당되겠죠.
s_Temp = (char **)malloc(sizeof(char *) * 3);
s_Temp[0] = (char *)malloc( 첫번째토큰길이 + 1 );
s_Temp[1] = (char *)malloc( 첫번째토큰길이 + 1 );
s_Temp[2] = (char *)malloc( 첫번째토큰길이 + 1 );
이렇게 된후에 그 s_Temp를 반환하죠.
그런데 질문하신분의 소스상
s_Temp[0 .. 2] 는 해제를 한거 같은데
정작 s_Temp는 할당을 해제하지 않으신듯 합니다.
즉 결론은
free_string_array(tmp,spit);
이 줄 밑에
free(tmp);
가 삽입되어야 할것으로 사료되옵니다.
Re: 질문의 답은 아닙니다만...
strdup와 getcwd는 POSIX와 WIN32 컴파일러에는 포함되어 있습니다만,
ANSI 표준에는 없습니다. 제가 언급한 문맥은 ANSI 표준을 말합니다.
하여튼 함수 자체에서 메모리를 동적 할당하여 리턴하는 것은 메모리 누수 버그 발생을 높이는 원인이 됩니다. 이러한 방식은 사용하지 않는 것이 좋습니다.
예, 표준이 지향하고자하는 것은 견고성보다는 이식성과 성능을 중요시하는 것이 맞습니다. 이것은 프로그래밍에 있어서의 일반적인 우선순위라고도 할 수 있습니다. 앞에도 썼듯이, 표준 라이브러리는 언어의 일부이므로 그 언어를 사용하는 프로그래머에게는 공통의 '어휘(vocabulary)' 역할을 합니다. 코드의 이식성과 가독성을 위한 기본적인 조건이 되지요. 이식성과 성능 문제를 해결한 다음에 견고성을 고려하는 것이 좋습니다. 최초의 프로토타입 개발 단계부터 견고성만 철저히 고려하다가는 코딩의 효율이 저하될 수 밖에 없습니다.
ANSI C 표준의 문자열 처리 함수들은 견고성이 형편없다는 점은 사실입니다. 표준 라이브러리 중 가장 취약한 분야중 하나죠. 이식성보다 견고성이 중요하다면 다른 라이브러리를 쓰실 것을 권합니다.
문자열 처리는 ANSI C++ 표준의 std::string을 쓰는 것이 이식성과 견고성 두가지를 모두 만족시키는 최선의 방법이라고 생각합니다.
C에서 저 같은 경우 메모리 해제는 핸들 방식을 씁니다.사용자는
C에서 저 같은 경우 메모리 해제는 핸들 방식을 씁니다.
사용자는 초기화 함수를 호출하여 특정 핸들을 얻습니다.
그다음 관련 함수들을 사용한 다음 핸들을 종료 함수에 넘겨주어 그 핸들과
관련된 메모리를 모조리 해제 하는 방법이죠.
대부분의 C 라이브러리 들은 사용자가 메모리를 할당해서 넘겨 주거나
저같이 핸들 방식으로 처리 하죠
C++ 같은 경우는 스마트 포인터를 사용합니다. 그게 구현양도 적으니까요.
無心
댓글 달기