4

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

誰でもこの問題を解決できますか... ありがとうございます。

4

5 に答える 5

6

buffer[16]char* get_timestamp()関数の最後で存在を停止するローカル配列です。次に、存在しない配列へのポインタを返します。

于 2013-03-15T15:24:04.997 に答える
4

スタック変数へのポインターを返しているため、関数が戻った後に使用することは無効です。

 char buffer[16];

関数内のスタックに割り当てられます。戻ると、スタックはクリーンアップされ、有効でbufferはなくなります。最小限の変更で、これはおそらくより良い関数シグネチャです:

void get_timestamp( char *buffer, size_t buffLen  )

bufferを呼び出す前に適切にスペースを割り当てていることを前提としていますget_timestamp

于 2013-03-15T15:24:40.243 に答える
2

他の人が言ったように、スタックに存在するデータを使用していて、それを宣言した関数を離れると存在しなくなります。この問題を解決するには、次の 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が、この状況ではやり過ぎのように思われ、説明した 2 つの修正よりもエラーが発生しやすくなります。

于 2013-03-15T15:36:50.863 に答える
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;
}
于 2016-12-16T21:08:04.783 に答える
1

返される文字列は自動変数です。関数を終了すると、この変数にアクセスできなくなります。仕様によると、未定義の動作です。malloc を使用して文字列を割り当てれば問題ありません。後で解放することを忘れないでください。

于 2013-03-15T15:28:42.830 に答える