Visual Studio 2015 の _utime32 関数で指定可能な時刻の上限が以前と異なる

こんにちは、Visual Studio サポート チームです。

今回は、Visual C++ で提供される _utime32 関数で指定可能な時刻の上限が、Visual Studio 2015 と以前のバージョンとで異なる現象についてご案内します。

 

現象:

Visual Studio 2015 で提供される Visual C++ の _utime32 関数の引数として、UTC 2038 年 1 月 18 日 23:59:59 (日本時間 2038 年 1 月 19 日 08:59:59) より後の時刻を指定すると処理に失敗してエラーとなり、戻り値として -1 が返ります。
これに対し、Visual Studio 2013 以前のVisual C++ では、UTC 2038 年 1 月 19 日 03:14:07 (日本時間 2038 年 1 月 19 日 12:14:07) まで指定可能となっていました。

 

原因 :

_utime や _futime 系の関数は、UTC からローカル時刻への変換のため、内部で localtime 関数を使用しています。
この localtime関数の引数の検証動作が、Visual Studio 2015 から変更されていることに起因して、_utime や _futime 関数で指定可能な引数の範囲に変化が生じています。
以下に、Visual Studio 2013 以前と Visual Studio 2015 での localtime 関数の動作の違いを説明します。

 

  • _Visual Studio 2013以前のバージョンでの動作 

Visual Studio 2013以前のバージョンでは、32 ビット版と 64 ビット版の localtime 関数において、time_t 型引数に対する検証処理が異なっておりました。
64ビット版では time_t が MAX__TIME64_T (0x793406fffi64 : UTC 3000 年 12 月 31 日 23:59:59) 以下であることを検証しています。
これに対し、32 ビット版では特別な検証は行っておらず、int 型の最大値 (0x7FFFFFFF : UTC 2038 年 1 月 19 日 03:14:07) まで指定可能となっていました。

 

  •    _Visual Studio 2015での動作

_Visual Studio 2015では、後述の Universal CRT の導入を機に、32ビット、64ビット版の localtime 関数が統合され、32 ビットの time_t 型引数についてもMAX__TIME32_T (0x7fffd27f : UTC 2038 年 1 月 18 日 23:59:59) 以下であることを検証する処理が追加されました。
このため、32 ビット版の localtime 関数において、Visual Studio 2013 以前で指定可能だった 0x7fffd27f ~ 0x7FFFFFFF の間の日時を、Visual Studio 2015 の localtime 関数で利用しようとすると、上記の検証処理により不正な引数として判定され、エラーが返る結果となります。
なお、64ビット版の localtime 関数では、Visual Studio 2013以前のバージョンと動作に差異はありません。

 

_MAX__TIME32_T と MAX__TIME64_T は、ctime.h ファイルに以下のように定義されています。

<ctime.h より抜粋>
#define _MAX__TIME32_T     0x7fffd27f

/* number of seconds from
00:00:00, 01/01/1970 UTC to
23:59:59, 01/18/2038 UTC */

#define _MAX__TIME64_T     0x793406fffi64

/* number of seconds from
00:00:00, 01/01/1970 UTC to
23:59:59. 12/31/3000 UTC */


必要な対応について:

32 ビットの time_t 型を使用している場合でも、元々、時刻の最大値を _MAX__TIME32_T (0x7fffd27f : UTC 2038 年 1月 18日 23:59:59) と想定しているアプリケーションであれば、上記の差異が問題となることはなく、特に対応が必要となることはありません。
そうではなく、_MAX__TIME32_T から int の最大値 (0x7fffd27f ~ 0x7FFFFFFF) の間の時刻を利用していたアプリケーションでは Visual Studio 2015 で _utime32 等を利用する場合は、時刻の上限をMAX__TIME32_Tとして利用するよう、アプリケーションを変更してください。

 

補足: Universal CRTについて

Visual Studio 2015 で提供される Visual C++ ランタイム (CRT) ライブラリは、それ以前のバージョンから構成が変更され、“Universal CRT” として提供されています。Universal CRT の詳細については、以下のVisual C++ Team Blog をご参照ください。

Visual C++ Team Blog : Introducing the Universal CRT (英語のみのご案内)
https://blogs.msdn.microsoft.com/vcblog/2015/03/03/introducing-the-universal-crt/

 

Visual Studio、または、Windows Software Development Kit (SDK) for Windows 10 をインストールした場合には、既定では以下のフォルダーに Universal CRT のソース コードが配置されますので、こちらから、Universal CRT の実装を確認することができます。

C:\Program Files (x86)\Windows Kits\10\Source\<バージョン番号>

なお、従来のバージョンの Visual C++ のソース コードについては、Visual Studio をインストールしている場合には、以下のフォルダーに配置されていますので、こちらを参照することが可能です。

C:\Program Files (x86)\<Visual Studioのインストール フォルダー>\VC\crt\src