2013-03-15 2 views
4

Я хочу получить временную метку для моего входа в систему c. Я написал функцию, чтобы получить timestamp. Но когда я возвращаю переменную i m, получаю другую ценность.Как получить временную метку в 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 too much boost –

+1

Почему вы отметили его Boost, C++ и C++ 11 ?? –

ответ

5

Вы возвращающая указатель на переменный стек и, следовательно, не является допустимым для использования после завершения функции:

char buffer[16]; 

будет выделен на стеке в функции. Когда вы возвращаете стек, очищается, а buffer больше недействителен. С минимальными изменениями это, вероятно, лучше функция подписи:

void get_timestamp(char *buffer, size_t buffLen ) 

предположение в том, что вы правильно выделили место для buffer перед вызовом get_timestamp.

+2

Любая функция, подобная этой, также должна принимать размер буфера, поскольку основная функция ('strftime()') должна знать размер буфера, чтобы предотвратить переполнение. – unwind

+0

@unwind хорошая точка, внесет поправки, спасибо –

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; 
} 

Примечания/Edit: Я сложил очень действительное замечание UNWIND в отношении передавая размер буфера в это предлагаемое решение.

Вариант 2: если вы не можете или не хотите менять подпись своей функции, вы можете использовать статическую переменную, но не забывайте, что статические переменные могут вызывать проблемы в многопоточных программах.

static char buffer[16]; 

char* get_timestamp(){ 
    ... 
} 

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

Можно, конечно, использовать malloc, но это кажется излишним в данной ситуации, и более подвержен ошибкам, чем два исправления, которые я описал.

+0

Возможно, лучше указать 'buffersize' как' size_t' –

+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; 
} 
Смежные вопросы