2016-09-09 12 views
1

最初に、謝罪:Cの新機能であり、一般的にコーディングではかなり緑色です。strftime(C)でポインタの宛先を使用

問題:strftime()を使用してCでタイムスタンプを作成しようとしています。 はこの作品:

#include <time.h> 
    ... 
    char timestamp[14]; 
    ...[code to define timestruct] 
    strftime(timestamp,15,"%Y%m%d%H%M%S", timestruct); 

しかしをこのがセグメンテーションフォールトを与える:

明らか
#include <time.h> 
    ... 
    char *timestamp; 
    ...[code to define timestruct] 
    strftime(timestamp,15,"%Y%m%d%H%M%S", timestruct); 

、私は機能するソリューションを持っているので、基本的にすべてが順調です。しかし、ポインタとしてのtimestampのバージョンはなぜ機能しないのですか?

ありがとうございます。

+1

最初に2番目のケースでタイムスタンプをmallocするようにしてください。つまり、 'char * timestamp = malloc(14)'を実行します。 – gowrath

+0

'strftime(timestamp、15、...')と呼ばれる2番目のケースの 'timestamp'は何ですか? – chux

+0

@gowrath – JMUP

答えて

1

Cのポインターでは、ヒープ上にポインターを割り当てる必要があります。最初のケースでは、char timestamp[14]を宣言すると、カッコ内の14は、タイムスタンプ用にスタックに14バイトを割り当てるようにコンパイラに指示しています。したがって、14バイトより短い文字列に使用するとうまくいくでしょう。

char *timestampを宣言しますが、メモリを割り当てないでください。したがって、strftimeが書き込もうとすると、無効なメモリに書き込んでアクセスできないため、segフォルトが発生します。これを修正するには、char *timestamp = malloc(14)と言ってタイムスタンプにメモリを割り当てる必要があります。これは、使用可能なヒープに割り当てられた14バイトのタイムスタンプを指します。この方法の問題点は、メモリ使用を完了した後でfree(timestamp)を呼び出すことによってメモリを手動で解放する必要があることです。

timestampが、自動的にクリーンアップされるため、その関数のスコープよりも長く存在する必要のないローカル変数の場合は、最初の方法が優先されます。

0

timestampはユニット化されたポインタであるため、strftimeがそれに書き込んでいるときはsegvです。

あなたは、ポインタを使用する場合は、呼び出し元にそれを返すローカルtimestampを使用しないようにしたい場合は、それはないとして、私は、最初のソリューションをお勧めしますmalloc

char *timestamp = malloc(20); // 20 is maybe too much, better safe than sorry 

を使用してメモリを割り当てます割り当て/割り当て解除が必要です。より速くより安全(メモリリークはありません)

0

strftime()には、フォーマットされた文字列を書き込むためのバッファーがtimestampに必要です。そのバッファ自体にメモリを割り当てません。 char timestamp[14]を使用するときに14文字のバッファがあり、ほとんど問題はありません。timestampの末尾に書き込まないように、15ではなくmaxの引数に14を送信してください。 char *timestampを使用している場合、ランダム値を含むポインタだけがありますが、メモリは割り当てられていません。 strftime()は、そのランダムなポインタを逆参照し、それが参照するメモリ内のどこにでも書き込もうとします。そして、そのメモリはどこにあるかによって異なります。存在しないとアクセスできない場合は、セグメンテーション違反が発生します。存在し、書き込み可能であれば動作するように見えますが、実際には、他のどこかで不明な部分が壊れてしまい、後でランダムなバグがポップアップする可能性があります。 timestampにcharの配列の代わりにchar *を使用する場合は、malloc()などを使用してメモリを割り当て、を呼び出す前に割り当てられたメモリを指し示すように結果をtimestampに割り当てる必要があります。

0

どちらのテストでも、未定義の動作(UB)が発生します。

  1. 最初のミス主導strftime()それにバッファサイズを伝えることによって、それがあったことを1大きかったです。バッファの外側に書くことはUBです。 OPはそれが「機能する」と報告していますが、それがUBの可能性の1つです。これは、不正なコードであると再記述する必要があります

    char timestamp[14]; 
    //     v 
    strftime(timestamp,15,"%Y%m%d%H%M%S", timestruct); 
    
    // Use this instead 
    
    char timestamp[15 /* or more */]; 
    strftime(timestamp, sizeof timestamp,"%Y%m%d%H%M%S", timestruct); 
    
  2. 第二は明らかにtimestampにそれがどこかとにそれを伝えるstrftime()に渡されるので、未定義のデータを価値を与えるものではありません。 timestampには未定義の値があるため、これはUBです。これは悪いコードであり、最初にメモリを割り当てるために書き直す必要があります。また

    char *timestamp; 
    ... 
    strftime(timestamp, 15, "%Y%m%d%H%M%S", timestruct); 
    
    // Use this instead 
    
    #define timestamp_N 15 
    { 
    char *timestamp = malloc(timestamp_N); 
    assert(timestamp); // Check allocation 
    ... 
    strftime(timestamp, timestamp_N, "%Y%m%d%H%M%S", timestruct); 
    ... // Use timestamp 
    free(timestamp); 
    } 
    

:1)年フィールドは、(+ 1900)9999 15 0000に限定されるものではない"%Y%m%d%H%M%S"のロバストな使用のためには不十分です。 2)バッファーサイズでとてもかすかな必要はほとんどありません。 64ビットのtm_yearフィールドに対処できる32のようなバッファサイズを提案する。 3)結果はタイムゾーンではありません。 UTCの場合はZを追加します。 4)標準ISO 8601を確認してください。

関連する問題