ユニバーサル 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(ライブラリを無視する)」 を参照してください。
注
ソース コードでは、setlocale() ではなく、_o_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- タイム ゾーン情報