2013-03-15 5 views
4

내 로그인을위한 타임 스탬프를 얻고 싶습니다. c. 나는 타임 스탬프를 얻기위한 함수를 작성했다. 하지만 변수를 반환 할 때 다른 값을 얻습니다.c에서 타임 스탬프를 얻는 방법

내 코드 :

#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 

char* get_timestamp(){ 
    time_t rawtime; 
    struct tm * timeinfo; 
    char buffer[16]; 
    time (&rawtime); 
    timeinfo = localtime (&rawtime); 
    strftime (buffer,16,"%G%m%d%H%M%S",timeinfo); 
    puts(buffer); 
    return buffer; 
} 

int main() 
{ 
    puts(get_timestamp()); 
    return 0; 
} 

출력 :

20130315204815 
Ir?0315204815 

사람이 밖으로 도울 수 ... 감사합니다.

+1

-1 부스트가 너무 많음 –

+1

왜 Boost, C++ 및 C++ 11로 태그를 지정 했습니까? –

답변

5

당신은 스택 변수에 대한 포인터를 반환하고 따라서이 함수가 반환 후 사용 유효하지 않습니다

char buffer[16]; 

은 함수의 스택에 할당됩니다. 반환하면 스택이 정리되고 buffer은 더 이상 유효하지 않습니다. 최소한의 변경이 아마 더 나은 함수 서명입니다 :

void get_timestamp(char *buffer, size_t buffLen ) 

제대로 get_timestamp를 호출하기 전에 buffer을위한 공간을 할당 한 것을되는 가정.

+2

오버 플로우를 막기 위해 핵심 함수 ('strftime()')가 버퍼 크기를 알아야하기 때문에이 함수는 버퍼 크기를 받아 들여야합니다. – unwind

+0

@wwind 좋은 지적, 고치고, 고맙다. –

6

buffer[16]은 로컬 배열이며 char* get_timestamp() 기능의 끝 부분에 존재하지 않습니다. 그런 다음 존재하지 않는 배열에 대한 포인터를 반환합니다.

1

반환 할 문자열이 자동 변수입니다. 함수를 종료 할 때이 변수에 액세스하는 것은 불가능합니다. 스펙에 따르면 정의되지 않은 동작입니다. 문자열을 할당하기 위해 malloc을 사용하면 괜찮을 것이다. 나중에 무료로 제공하는 것을 잊지 마십시오.

2

다른 말로하면, 스택에있는 데이터를 사용하고 선언 한 함수를 떠나면 기존 데이터가 중지됩니다.

옵션 1 : :이 문제를 해결하기 위해 두 가지 간단한 가능성을 볼 수있는 호출하는 함수에 버퍼 변수를 할당하고 get_timestamp에

void get_timestamp(char *buffer, size_t buffersize) { 
    .... 
    strftime (buffer,buffersize,"%G%m%d%H%M%S",timeinfo); 
} 

int main() 
{ 
    char buffer[16]; 
    puts(get_timestamp(buffer,16)); 
    return 0; 
} 

주/편집 포인터를 전달 : 나는에 대한 언 와인드의 매우 유효한 발언을 접어 이 제안 된 솔루션에 버퍼 크기를 전달합니다.

옵션 2 : 함수의 서명을 변경할 수 없거나 변경하지 않으려는 경우 정적 변수를 사용할 수 있지만 정적 변수가 다중 스레드 프로그램에서 문제를 일으킬 수 있음을 잊지 마십시오.

static char buffer[16]; 

char* get_timestamp(){ 
    ... 
} 

int main() 
{ 
    puts(get_timestamp()); 
    return 0; 
} 

당신은 물론 malloc를 사용할 수 있지만,이 상황에서 과잉 것, 그리고 내가 설명이 수정보다 오류가 발생하기 쉽습니다입니다.

+0

아마도'size_t'로'buffersize'를 지정하는 것이 더 좋다. –

+0

세련된 응답을 주셔서 감사합니다 ... –

+0

@ShafikYaghmour 실제로, 나는 그에 따라 내 대답을 편집 할 것입니다. – fvu

1

나는이 질문에 대답하면서 간단하고 스레드 친화적 인 char * (스레드는 관리하기가 지루한) *를 반환하지 않았으며 스레드로부터 안전하며 자체 발 앞에 서기를 원했습니다. 필자는 관리해야하는 char * 또는 포인터를 반환하는 함수에 대한 혐오감을 가지고 있습니다.

아래 함수는 malloc을 호출하지 않습니다.

이 함수는 매개 변수를 사용하지 않고 타임 스탬프를 반환합니다. 나는 그것이 잘 작동한다고 생각한다.

struct Timestamp { 
    time_t seconds; 
    long milliseconds; 
    char timestring[32]; 
}; 


struct Timestamp getTimestamp() 
{ 
char timebuffer[32]  = {0}; 
struct timeval tv  = {0}; 
struct tm  *tmval  = NULL; 
struct tm  gmtval = {0}; 
struct timespec curtime = {0}; 

struct Timestamp timestamp; 

int i = 0; 

// Get current time 
clock_gettime(CLOCK_REALTIME, &curtime); 


// Set the fields 
timestamp.seconds  = curtime.tv_sec; 
timestamp.milliseconds = round(curtime.tv_nsec/1.0e6); 

if((tmval = gmtime_r(&timestamp.seconds, &gmtval)) != NULL) 
{ 
    // Build the first part of the time 
    strftime(timebuffer, sizeof timebuffer, "%Y-%m-%d %H:%M:%S", &gmtval); 

    // Add the milliseconds part and build the time string 
    snprintf(timestamp.timestring, sizeof timestamp.timestring, "%s.%03ld", timebuffer, timestamp.milliseconds); 
} 

return timestamp; 
} 

int main() 
{ 
    char timebuffer[64]  = {0}; 
    int i = 0; 
    struct timespec sleeptime = {0, 5000000L}; 

    struct Timestamp timestamp; 

    for (i=0; i < 20; i++) 
    { 
     timestamp = getTimestamp(); 
     printf("Time is: %s \n", timestamp.timestring); 
     nanosleep(&sleeptime, NULL); 
    } 

    return 0; 
} 
관련 문제