CRT でのグローバル状態
ユニバーサル C ランタイム (UCRT) の一部の関数は、グローバル状態を使用します。 たとえば、setlocale()
はプログラム全体のロケールを設定します。これは、桁区切り記号、テキスト コード ページなどに影響します。
UCRT のグローバル状態は、アプリケーションと OS 間では共有されません。 たとえば、アプリケーションが setlocale()
を呼び出す場合、C ランタイムを使用する OS コンポーネントのロケールや、その逆の方法には影響しません。
CRT 関数の OS 固有バージョン
UCRT では、グローバル状態を使用してやり取りする関数には、先頭に _o_
が付く "ツイン" 関数があります。 次に例を示します。
setlocale()
アプリ固有のグローバル状態に影響します。_o_setlocale()
アプリではなく、すべての OS コンポーネントによって共有されるグローバル状態に影響します。
これらの "ツイン" 関数の唯一の違いは、グローバル CRT 状態の読み取り/書き込みを行うときに OS 固有のバージョン (つまり、_o_
で始まるバージョン) では、アプリのグローバル状態のコピーではなく、グローバル状態の OS コピーを使用することです。
これらの関数の OS 固有のバージョンは、ucrt.osmode.lib
にあります。 たとえば、setlocale()
の OS 固有バージョンは _o_setlocale()
です
コンポーネントの CRT 状態をアプリの CRT 状態から分離するには、次の 2 つの方法があります。
- コンパイラ オプション
/MT
(リリース) または/MTd
(デバッグ) を使用して、コンポーネントを静的にリンクします。 詳細については、/MD、/MT、/LD に関する記事を参照してください。 静的リンクを使用すると、バイナリ サイズを大幅に増やすことができます。 - Windows 10 バージョン 2004 以降の Windows バージョンでは、CRT に動的にリンクしますが、OS モードのエクスポート (o で始まる関数) を呼び出します。 OS モードのエクスポートを呼び出すには、前と同じように静的にリンクしますが、リンカー オプション
/NODEFAULTLIB:libucrt.lib
(リリース) または/NODEFAULTLIB:libucrtd.lib
(デバッグ) を使用して静的 UCRT を無視します。ucrt.osmode.lib
をリンカー入力に追加します。 詳細については、「/NODEFAULTLIB
(ライブラリを無視する) 」を参照してください。
Note
ソース コードでは、_o_setlocale()
ではなく、setlocale()
を記述します。 ucrt.osmode.lib
に対してリンクすると、リンカーは自動的に OS 固有の関数のバージョンに置き換えます。 つまり、setlocale()
は _o_setlocale()
に置き換えられます。
ucrt.osmode.lib
に対するリンクは、アプリ モードでのみ使用できる一部の UCRT 呼び出しを無効にします。 これらの関数を呼び出そうとすると、リンク エラーが発生します。
アプリと OS の分離によって影響を受けるグローバル状態
アプリと OS の状態を分離することによって影響を受けるグローバル状態には、次のものが含まれます。
- ロケール データ
- シグナル ハンドラーの設定
signal
- によって設定される終了ルーチン
terminate
errno
および_doserrno
- とで
rand
使用される乱数生成状態srand
- ユーザーが解放する必要のないバッファーを返す関数:
strtok
、wcstok
_mbstok
Tmpnam
,_wtmpnam
asctime
,_wasctime
gmtime
,_gmtime32
,_gmtime64
_fcvt
_ecvt
strerror
,_strerror
,_wcserror
,__wcserror
- で使用される
_putch
バッファー_putwch
_set_invalid_parameter_handler
,_set_thread_local_invalid_parameter_handler
_set_new_handler
および_set_new_mode
fmode
- タイム ゾーン情報