C 언의 localtime() 함수에 대해서

NeoCode24의 이미지

다름이 아니라 localtime() 사용시의 주의 사항에 대해서 나름대로 분석을 해 보앗는데..

잘 맞는 지.. 틀린부분이나 좀더 개념적인 부분에 설명이 필요한 부분에 고수님들의 조언을 부탁드립니다. ^^

자세한 원형은 이것과 유사하리라 생각합니다.

struct tm* localtime(long *)

long 타입 시간값의 포인터를 인자로 받아
struct tm 구조체 포인터를 반환해 주는 것으로 알고 있는데요.(맞나?? ^^;;)

제가 사용하다가 발견한 문제점은..

localtime() 함수를 사용후 반환 받는 (struct tm *) 이것은 안전성이 보장 되지 않는 것이지 않는 가 입니다.

localtime()에서 처리 하는 원형을 알고 싶기는 한데..

일단 생각해 보면 localtime() 함수 안에서 (struct tm)를 선언할테고 그안에 연산을 통해 각 구조체 값에

년, 월, 일, 시, 분... 등등 대입 후 (struct tm *)를 반환할꺼 라고 생각합니다.

함수를 떠나면 (struct tm) 변수는 사라지는게 원칙이고 그 포인터를 반환해줬기 때문에

함수의 반환을 받은 자는 실효성 없는 구조체를 사용한다고 생각합니다..

때문에 다른 곳에서 어떤 메모리 처리를 하게 되면 localtime() 안에서 만든 (struct tm) 위치를 덮어서

다른값으로 변경되지 않는가가 질문의 요지 입니다.

물론 현재 이런 문제가 발생했는데..

그 예는 다음과 같습니다.

--------------------------------------------------------------

long lCurTime = 0;
struct tm *pstCurTime;
char temp[20];

lCurTime = time((time_t*)NULL);

/* 1시간 전 값으로 */
lCurTime = lCurTime - 3600;

pstCurTime = localtime(&lCurTime);


/* printf와 유사하지만 time를 찍어주는 log 함수 : 내부적으로 time, localtime 사용 */
/* 2006-07-12 09:50:31 (Hourly)Before Time[324234234] <-- 위와 같이 시간 출력 */
Log(LOG_DEBUG, "(Hourly)Before Time[%ld]\n", lCurTime);

strcat((char *)sqlCmd.arr, " WHERE collectingdate = to_char(to_date('");

memset(temp, 0x00, sizeof(char) * 20);

sprintf(temp, "%d-%d-%d", pstCurTime->tm_year+1900, pstCurTime->tm_mon+1, pstCurTime->tm_mday);

----------------------------------------------------------------

예를 들어 위와 같이 사용하면

제일 마지막 라인에 사용되는 pstCurTime값은 - 3600 된 값이 아닌 Log() 함수에서 현재시간을 찍은

그 값이 나온다는 말입니다.
(메모리 번지가 뒤집혀 지기 때문에 시스템 마다 다른값이 나올수도 있겠지요??)

때문에 해결책으로

------------------------------------------------------------------------

struct tm stTempTime;

pstCurTime = localtime(&lCurTime);

memcpy(&stTempTime, pstCurTime, sizeof(struct tm));

------------------------------------------------------------------------

이와 같이 복사 해서 해결했습니다.

반환 받은 (struct tm *)을 바로 스칼라 변수에 복사해서 안전하게 만들고

이후에 사용은 스칼라 변수만 사용했습니다.

이렇게 하니 Log() 함수에서 내부적으로 사용되는 time(), localtime()과는 충돌이 발생하지 않더군요..

어찌 분석이 잘 맞는지는 모르겠지만.. 좀더 구체적인 설명이나.. 근거 자료가 있으신분은 부탁드립니다

그럼 다들 즐프 하세요 ^^

cwryu의 이미지

struct tm 변수 하나를 C 라이브러리 어딘가에 저장해 놓고 같은 포인터만 리턴하기 때문이겠죠.

사실 위의 예보다 더 큰 문제가 되는 게 thread safe하지 않다는 점인데 (어떤 플랫폼의 경우에는 thread specific storage를 사용하기 때문에 스레드에도 안전하긴 하지만), 그 경우 localtime_r()을 쓰면 됩니다.

NeoCode24의 이미지

localtime_r()

struct tm * localtime_r (const time_t *time, struct tm *resultp)

이런것이 잇었군요.. 검색을 못한 것이 결국 여러번 꼬여서 해결을 하고 있었네요 ^^;;

감사 드려요.. 좋은 것 하나 배웠습니다 ^^

doldori의 이미지

struct tm stTempTime;
 
pstCurTime = localtime(&lCurTime);
 
memcpy(&stTempTime, pstCurTime, sizeof(struct tm));

는 간단하게
struct tm stTempTime = *localtime(&lCurTime);

로 하셔도 돼요.

아참, 그리고 localtime()의 인자는 long*이 아니고 time_t*입니다.
typedef long time_t 로 되어 있다면 그게 그거이긴 하지만
그렇지 않을 수도 있으니까...

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.