* strtok() 사용시 주의사항
C, C++ 언어 사용시 문자열을 자르는 처리 할 경우 주로 strtok()과 strtok_r() 함수를 사용합니다.
여기서 중요한 점은 strtok() 함수가 multi-thread 프로그램에서 오류를 유발할 수 있으므로, multi-thread 프로그램 구현 시
strtok_r() 함수를 사용해야 합니다.
#include <string.h> char *strtok(char *str, const char *delim); char *strtok_r(char *str, const char *delim, char **saveptr); |
strtok() 함수는 str문자열을 delim에 포함된 문자들 중에서 하나를 만나는 곳을 null-terminated 문자열로 변경하여 return 합니다.
str 문자열이 NULL이면 그 다음 delimiter까지의 문자열을 return합니다.
strtok_r() 함수의 saveptr은 문자열을 strtok()의 내부에서 관리하던 static 변수 대신에 외부 변수를 사용하도록 변경하여
multi-thread에 안전하도록 설계되었습니다.
* strtok() 함수 원형
char *strtok (char *s, const char *delim) { static char *olds; return __strtok_r (s, delim, &olds); } |
strtok() 함수의 내부에서 static char *olds 선언 후 __strtok_r() 함수를 호출하여 해당 값을 반환하는 과정에서 *olds 는 static으로 선언되어 프로그램의 data 영역에 저장됩니다.
즉, 최초 초기화 이후 프로그램 종료 시점까지 메모리 공간에 존재하는 전역변수의 특성을 가집니다.
따라서 strtok() 함수를 multi-thread 에서 사용하게 되면 예게치 못한 동작이 발생하게 됩니다.
strtok_r() 과 같이 multi-thread 에서 실행시 문제가 없는 함수를 thread-safe 함수라고 하는데,
이는 함수 내에서 전역 변수를 사용하지 않거나, 쓰레드에서 사용되는 공유자원을 lock 같은 동기화 기법으로 보호하여 공유 자원의 무결성을 보장합니다. strtok_r() 처럼 표준 함수 이름에 _r이 붙은 함수들은 thread-safe 한 함수들 입니다.
* strtok_r() 함수 원형
char * __strtok_r (char *s, const char *delim, char **save_ptr) { char *end; if (s == NULL) s = *save_ptr; if (*s == '\0') { *save_ptr = s; return NULL; } /* Scan leading delimiters. */ s += strspn (s, delim); if (*s == '\0') { *save_ptr = s; return NULL; } /* Find the end of the token. */ end = s + strcspn (s, delim); if (*end == '\0') { *save_ptr = end; return s; } /* Terminate the token and make *SAVE_PTR point past it. */ *end = '\0'; *save_ptr = end + 1; return s; } |
'C · C++' 카테고리의 다른 글
C++ STL 컨테이너 공유메모리 사용법 (0) | 2021.01.14 |
---|---|
헤더와 라이브러리 비교 (1) | 2020.06.03 |
이차원 포인터와 포인터 배열 및 배열 포인터 (0) | 2020.04.24 |
배열과 포인터의 메모리 차이 (1) | 2020.04.22 |
const int*와 int* const 차이 (2) | 2020.04.21 |