strdup 에 대해서...
글쓴이: song / 작성시간: 수, 2003/07/09 - 11:16오전
다음 예제 1과 2의 차이점을 알고 싶습니다.
strdup를 쓰면 메모리를 해제 시켜야 하는 점이 있는데 굳이 strdup을 썼다면 그 이유가 무엇일까요?
예제1 :
names = strdup("a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z");
printf("input: %s\n", names);
count = unique_name_vector(names, ',', vector, 20);
printf("count: %d\n", count);
printf("output:");
for (i = 0; i < count; ++i)
printf(" %s", vector[i]);
printf("\n");
free(names);
예제 2:
*names = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z";
printf("input: %s\n", names);
count = unique_name_vector(names, ',', vector, 20);
printf("count: %d\n", count);
printf("output:");
for (i = 0; i < count; ++i)
printf(" %s", vector[i]);
printf("\n");
Forums:
.답변
1.2 의 차이점은
1은 names 가 힙에 저장되고
2는 names 가 스택에 저장됩니다.
위의 예제에서는 수행결과가 별 차이가 없지만.
2번의 예제를 함수를 이용해 호출한뒤 names 를 리턴해 보시면 리턴값이 신뢰할수 없다는것을 발견하실겁니다.
strdup 는 파라미터로 받은 문자열을 malloc 으로 새로 잡아 그 주소를 리턴합니다.
이는 특정 str* (strtok () )함수들을 사용시
인자로 받은 문자열을 토큰으로 분리하면서 원본 인자를 변경하게됩니다.
따라서 gnu glibc 레퍼런스를 참조 하시면
strdup 를 사용해서 새로운 문자열에 대한 포인터를 받아서 사용하고 있습니다.
제 생각에는 strdup 가 특별한 용도로 제작된게 아니라 string.h 내의 함수를 사용시 편의를 위해 strdup를 만들어 놓은게 아닌가 합니다.
물론 제 생각일 뿐입니다. ㅡ.ㅡ;
무인도에 갇힌다면 당신이 가지고 갈 세가지는?
일단 다음의 경우는 내부에 할당되지 않는 초기화된 데이터로 컴파일되어
일단 다음의 경우는 내부에 할당되지 않는 초기화된 데이터로 컴파일되어
실행파일내에 내장됩니다.
"a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z"
이것을 char *names에 대입을 하였다면
그것은 그 자체를 뜻하는 것이고
strdup 에 의해서 반환된 값을 names에 대입하였다면
그 자체를 의미하는 것이 아니라 새로이 할당된 메모리로의 복사본을
뜻합니다.
반드시 strdup에 의해 반환된것은 free로 할당을 해제하여야 합니다.
strdup를 쓰는 이유는 여러가지가 있지만
주로 내부적으로 문자열 원본에 수정을 가하지 않게 하기 위함입니다.
만약 strdup를 쓰지 않았다면
다음의 경우를 해보시면 그 쓰이는 용도를 이해하실수 있을거라 사료됩니다.
void TestIDATA_0( char *s_String )
{
char *s_Copy = s_String;
s_Copy[ 0 ] = 'N';
fprintf(stdout, "[%s][%s]\n", s_String, s_Copy);
}
void TestIDATA_1(const char *s_String )
{
char *s_Copy = strdup(s_String);
if(s_Copy)
{
s_Copy[ 0 ] = 'N';
fprintf(stdout, "[%s][%s]\n", s_String, s_Copy);
free(s_Copy);
}
}
int main(...)
{
TestIDATA_0( "Hello Test #0");
TestIDATA_1( "Hello Test #1");
}
예제 2의 문자열은 상수이므로 변경이 불가능하니까그런 경우에 손쉽게
예제 2의 문자열은 상수이므로 변경이 불가능하니까
그런 경우에 손쉽게 복사본을 얻기 위해서 예제 1의 형식을 쓰지 않을 까요.
그리고 names가 상수에 대한 포인터라 names 자체의 extent의 유효여부는 문제가 되지않을 것 같은데요. return 해 쓰셔도 무방하지 않을까요.
오늘 우리는 동지를 땅에 묻었습니다. 그러나 땅은 이제 우리들의 것입니다.
아직도 우리의 적은 강합니다. 그러나 우리는 그들보다 많습니다.
항상 많을 것입니다.
strsep()
위와 같은 이유로, 커널 라이브러리를 보면, strtok()대신
strsep()를 사용하길 권장하고 있습니다. 같은 용도의 함수지만
strsep()는 원본 문자열을 변경하지 않습니다.
Follow the way of your heart
And whatever your eyes see,..
Re: strdup 에 대해서...
소유권 문제입니다.
대개의 이런 경우에 return 되는 값이 내용은 같을 지라도, 인자로 받은 것을 내부의 static 변수등에 담아 그 변수의 pointer를 보내는 함수와
malloc 한 pointer를 넘기는구현이 있습니다.
포인터 문제는 참조만 하느냐와 자신이 해제해야할 의무가 있느냐(소유하고 있느냐)에 따라 적절하게 설계상의 선택이 필요한 문제로 바뀌게 됩니다.
---
http://coolengineer.com
.
제가 잘못 생각했습니다.
확인해 보니 로컬 문자열 상수도 스택에 저장이 될꺼라고 생각했는데 static 에 저장되는군요.
위에 작성한 리턴값의 신뢰성에 대한 내용은 잘못된 내용이네요.
배열 같은경우
char a[] = "test message";
char *b = "test message";
a 는 문자열 상수의 복사가 이루어져서 스택에 저장 되지만
b 같은 경우는 문자열 상수의 static 영역의 주소값이 저장이 되기 때문에
리턴값을 사용할수 있습니다.
무인도에 갇힌다면 당신이 가지고 갈 세가지는?
댓글 달기