From 0d0c489493c7f6a765eca712991593caa0165687 Mon Sep 17 00:00:00 2001 From: Koichi Murase Date: Wed, 3 Dec 2025 10:28:57 +0900 Subject: [PATCH 1/3] =?UTF-8?q?fix(cstdlib/mblen):=20=E8=AB=B8=E3=80=85?= =?UTF-8?q?=E3=81=AE=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * std::mblen の内部状態をクリアせずに使用しているのを修正 * size_t に対する std::size_t のつけ忘れを修正 * nullptr を指定した時の戻り値の記述を修正 * 関連するロカールカテゴリを明記 --- reference/cstdlib/mblen.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/reference/cstdlib/mblen.md b/reference/cstdlib/mblen.md index 4cdcd924d0..e205197371 100644 --- a/reference/cstdlib/mblen.md +++ b/reference/cstdlib/mblen.md @@ -14,13 +14,13 @@ namespace std { 先頭以外の文字に関するバイト数は計算されない。 -この関数は現在のロケールに依存してマルチバイト文字を解釈する。 +この関数は現在のロケールカテゴリー `LC_CTYPE` に依存してマルチバイト文字を解釈する。 `n`は解析に使用する最大バイト数を指定する。 ## 戻り値 - 正常に動作する場合、文字の占めるバイト数を返す。 -- `str`が`nullptr`の時、内部状態を初期化し`0`を返す。 +- `str`が`nullptr`の時、内部状態を初期化する。現在のエンコーディングが状態を持つ場合は非ゼロの値を返し、それ以外の場合は`0`を返す。 - 無効な文字列、または`n`が不足している場合、`-1`を返す。 ## 例 @@ -51,8 +51,11 @@ int main() { #include int count_chars_mblen(const char* s) { + // std::mblen 内部の std::mbstate_t を初期化する必要あり + std::mblen(nullptr, 0); + int count = 0; - size_t i = 0; + std::size_t i = 0; while (s[i] != '\0') { int len = std::mblen(&s[i], MB_CUR_MAX); if (len < 0) { From 4a9b8871d00120f54b5a08b1e0e7e35917b2e56f Mon Sep 17 00:00:00 2001 From: Koichi Murase Date: Wed, 3 Dec 2025 11:01:35 +0900 Subject: [PATCH 2/3] =?UTF-8?q?fix(cstdlib/mblen):=20=E3=83=90=E3=83=83?= =?UTF-8?q?=E3=83=95=E3=82=A1=E3=82=AA=E3=83=BC=E3=83=90=E3=83=BC=E3=83=A9?= =?UTF-8?q?=E3=83=B3=E3=81=AE=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 残り MB_CUR_MAX バイトが読み取れることが保証されていないと未定義動作 Co-authored-by: Raclamusi <61970673+Raclamusi@users.noreply.github.com> --- reference/cstdlib/mblen.md | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/reference/cstdlib/mblen.md b/reference/cstdlib/mblen.md index e205197371..4bdf01934d 100644 --- a/reference/cstdlib/mblen.md +++ b/reference/cstdlib/mblen.md @@ -26,14 +26,15 @@ namespace std { ## 例 ### 基本的な使い方 ```cpp example -#include -#include #include +#include +#include +#include int main() { std::setlocale(LC_ALL, "ja_JP.UTF-8"); const char *str = "こんにちは"; - int result = std::mblen(str, MB_CUR_MAX); + int result = std::mblen(str, std::strlen(str)); std::cout << result << std::endl; return 0; } @@ -46,9 +47,10 @@ int main() { ### 文字列の文字数を計算する ```cpp example -#include -#include #include +#include +#include +#include int count_chars_mblen(const char* s) { // std::mblen 内部の std::mbstate_t を初期化する必要あり @@ -56,8 +58,9 @@ int count_chars_mblen(const char* s) { int count = 0; std::size_t i = 0; - while (s[i] != '\0') { - int len = std::mblen(&s[i], MB_CUR_MAX); + std::size_t bytes = std::strlen(s); + while (i < bytes) { + int len = std::mblen(&s[i], bytes - i); if (len < 0) { len = 1; } From 3dc288591ad11b8e493dc7638f20c7a00424253a Mon Sep 17 00:00:00 2001 From: Koichi Murase Date: Wed, 3 Dec 2025 10:48:37 +0900 Subject: [PATCH 3/3] =?UTF-8?q?fix(cstdlib/mblen):=20=E5=86=85=E9=83=A8?= =?UTF-8?q?=E7=8A=B6=E6=85=8B=E3=81=A8=20std::mbrlen=20=E3=82=92=E8=A8=80?= =?UTF-8?q?=E5=8F=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- reference/cstdlib/mblen.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/reference/cstdlib/mblen.md b/reference/cstdlib/mblen.md index 4bdf01934d..c38e3d3d84 100644 --- a/reference/cstdlib/mblen.md +++ b/reference/cstdlib/mblen.md @@ -18,6 +18,11 @@ namespace std { `n`は解析に使用する最大バイト数を指定する。 +この関数は `std::mbstate_t` に等価な静的記憶域の内部状態を保持し、前回の `mblen` 関数呼び出しの続きとして処理を行う。 +従って、この関数はスレッドセーフではない。 +スレッドセーフに処理する場合は、`std::mbstate_t` を受け取る [`std::mbrlen`](../cwchar/mbrlen.md.nolink) (``) を使い、呼び出し元でデコード状態の記録場所 `std::mbstate_t` を用意する必要がある。 +新しいコードでは、特に理由がない限り `std::mblen` ではなく `std::mbrlen` を用いるべきである。 + ## 戻り値 - 正常に動作する場合、文字の占めるバイト数を返す。 - `str`が`nullptr`の時、内部状態を初期化する。現在のエンコーディングが状態を持つ場合は非ゼロの値を返し、それ以外の場合は`0`を返す。 @@ -79,8 +84,15 @@ int main() { } ``` +注意: この例は飽くまで `std::mblen` を用いて文字数を数える関数の例であるが、実用上は `std::mbrlen` を用いた実装にするのが安全である。 +上の関数 `count_chars_mblen` はスレッドーセーフでない他、呼び出し元でも `std::mblen` を使っている場合にその振る舞いを破壊する可能性がある。 + #### 出力例 ``` 文字列: こんにちは世界 文字数: 7 ``` + +## 関連項目 + +- [`mbrlen`](../cwchar/mbrlen.md.nolink): `std::mbstate_t` を受け取るスレッドセーフなバージョン