web-dev-qa-db-ja.com

ローカル時間の結果構造体はCでどのように割り当てられますか?

時間/日関数を支援するCのtime.hファイルで遊んでいました。

私は遭遇しました:

struct tm * _Cdecl localtime(const time_t *__timer);

...これはtm構造体へのポインタを返すようです。アドレスによるリターンは、主に新しいメモリ割り当てを返すために使用されることがわかりました。

その場合、上記のリターンは実際にどのように機能しますか(struct tmのリターンアドレス)。返されたオブジェクトはどこかに定義されていますか?

ありがとう

36
Akash

localtime(および他のいくつかの関数)によって返されるポインターは、実際には静的に割り当てられたメモリーへのポインターです。 だからあなたは解放する必要はありません。さらに、それを解放するべきではありません。

http://www.cplusplus.com/reference/clibrary/ctime/localtime/

この構造は静的に割り当てられ、関数gmtimeとlocaltimeによって共有されます。これらの関数のいずれかが呼び出されるたびに、この構造の内容が上書きされます。

編集:コメントに記載されているいくつかの項目を追加します。

この共有データ構造の直接的な結果は、localtimeおよび同様の関数がスレッドセーフではないということです。スレッドセーフソリューションは、プラットフォームによって異なります。 localtime_r for POSIX および localtime_s for MSVC

48
Mysticial

静的に割り当てられたメモリへのポインタを返します(おそらく、static内で定義されたlocaltime変数、またはCランタイムライブラリのどこかで定義されたグローバル)。そのようなメモリを解放してはなりません。

明らかに、この関数は再入可能ではありません(ただし、TLSが使用されている場合はスレッドセーフになる可能性があります)。

このポインタを使用するときは注意が必要です。ポインタの使用を終了する前に、localtime/gmtime/...を呼び出す可能性のある関数呼び出しを行わないでください。そうしないと、によって参照されるメモリの内容がポインタが変更される可能性があり(localtimeへの新しい呼び出しに応答して)、別のtime_tに関連する値を読み取ることになります。

一般に、日付/時刻ライブラリの設計はかなり時代遅れです。この種の最適化は、C言語が設計されたときに価値がありましたが、今日では問題が発生するだけです。

これらの問題に対処するために、これらの関数には少なくとも2つの異なる改良バージョンがあります。localtime_r(SUSv2、rは「再入可能」のままです)とlocaltime_s(Microsoft、s「安全」のためにとどまります)。移植性の悲しい事実は、これらはほとんど同じことをしますが(宛先struct tmをパラメーターとして渡す必要があります)、パラメーターの名前と順序が異なります。

11
Matteo Italia

manページ は言う:

戻り値は、静的に割り当てられた構造体を指します。この構造体は、日付と時刻の関数への後続の呼び出しによって上書きされる可能性があります。

また:

Localtime_r()関数も同じことを行いますが、データをユーザー指定の構造体に格納します。 tzname、timezone、およびdaylightを設定する必要はありません。

5
Kos

実際、localtimeは通常、静的オブジェクトのアドレスを返します。私はそれがこのように見えると思う:

struct tm *
localtime(const time_t *timer)
{
    static struct tm tm;

    /* Magic. */

    return &tm;
}
3
cnicutar

これらは、ライブラリにローカルな静的構造体へのポインタを返します。マニュアルページから:

注
 
 4つの関数asctime()、ctime()、gmtime()、localtime()は
静的データへのポインターを返すため、スレッドセーフではありません。スレッドセーフ
バージョンasctime_r()、ctime_r()、gmtime_r()、localtime_r()はSUSv2で指定されており、libc5.2.5以降で使用できます。
 
 POSIX.1-2001の説明:「asctime()、ctime()、gmtime()、およびlocaltime()
関数は、2つの静的オブジェクトのいずれかで値を返します:壊れた-
ダウンタイム構造とchar型の配列。
関数のいずれかを実行すると、これらの
オブジェクトのいずれかで返された情報が他の関数によって上書きされる可能性があります。」これは、glibc 
の実装で発生する可能性があります。
3
Brian Roach

localtime関数によって返されるポイントされたオブジェクトには、静的な保存期間があります。

0
ouah