From 90c7ce3789863a8abf9aa9d2850448650cd22f86 Mon Sep 17 00:00:00 2001 From: Akira Takahashi Date: Fri, 13 Sep 2024 19:22:42 +0900 Subject: [PATCH 01/21] =?UTF-8?q?C++26=20:=20=E3=80=8C=E6=9C=AA=E5=88=9D?= =?UTF-8?q?=E6=9C=9F=E5=8C=96=E5=A4=89=E6=95=B0=E3=81=AE=E8=AA=AD=E3=81=BF?= =?UTF-8?q?=E5=8F=96=E3=82=8A=E3=82=92=E8=AA=A4=E3=82=8A=E8=B5=B7=E5=9B=A0?= =?UTF-8?q?=E5=8B=95=E4=BD=9C=E3=81=A8=E3=81=99=E3=82=8B=E3=80=8D=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- GLOBAL_DEFINED_WORDS.json | 4 + implementation-status.md | 2 +- lang/cpp26.md | 2 +- ...oneous_behavior_for_uninitialized_reads.md | 121 ++++++++++++++++++ 4 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 lang/cpp26/erroneous_behavior_for_uninitialized_reads.md diff --git a/GLOBAL_DEFINED_WORDS.json b/GLOBAL_DEFINED_WORDS.json index f9944b32cc..c87f83a9d2 100644 --- a/GLOBAL_DEFINED_WORDS.json +++ b/GLOBAL_DEFINED_WORDS.json @@ -23,6 +23,10 @@ }, "未規定動作": { "redirect": "未規定の動作", "yomi": "みきていどうさ" }, "未規定": { "redirect": "未規定の動作", "yomi": "みきてい" }, + "誤り起因動作": { + "yomi": "あやまりきいんどうさ", + "desc": "誤った操作に対する結果が明確に定義された動作。erroneous behavior (EB)。処理系によって診断や異常終了を実行することが許可されるが、処理が続行する場合もある" + }, "処理系定義の動作": { "link": "/implementation-compliance.md#dfn-implementation-defined-behavior", "yomi": "しょりけいていぎのどうさ", diff --git a/implementation-status.md b/implementation-status.md index aa8f351fae..d26f038dc0 100644 --- a/implementation-status.md +++ b/implementation-status.md @@ -305,7 +305,7 @@ | P0609R3: [構造化束縛への属性を許可](/lang/cpp26/attributes_for_structured_bindings.md) | `auto [a, b [[maybe_unused]], c] = f();`のように構造化束縛の要素に対して属性を付加できるようにする | 15 | 19 | | | | P3034R1: [モジュール宣言でのモジュール名のマクロ展開を禁止する](/lang/cpp26/module_declarations_shouldnt_be_macros.md.nolink) | `export module MACRO_NAME;`を禁止 | | | | | | P2809R3: [自明な無限ループは未定義動作ではないと規定](/lang/cpp26/trivial_infinite_loops_are_not_undefined_behavior.md.nolink) | 並行プログラムの進行保証などを考慮して無限ループを未定義動作ではないものとする | 14 | 19 | | | -| P2795R5: [未初期化変数の読み取りを不正動作 (erroneous behaviour: EB) とする](/lang/cpp26/erroneous_behaviour_for_uninitialized_reads.md.nolink) | 初期化されていない自動変数の読み取りの安全性を規定する | | | | | +| P2795R5: [未初期化変数の読み取りを誤り起因動作とする](/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md) | 初期化されていない自動変数の読み取りの安全性を規定する | | | | | | P2573R2: [関数宣言を削除する理由を指定できるようにする](/lang/cpp26/delete_reason.md) | `f() = delete("reason");` | 15 | 19 | | | | P2893R3: [可変引数テンプレートで`friend`宣言をできるようにする](/lang/cpp26/variadic_friends.md.nolink) | クラステンプレートの可変引数テンプレートでまとめて`friend`宣言できるようにする | 15 | | | | | P2747R2: [`constexpr`配置`new`](/lang/cpp26/constexpr_placement_new.md.nolink) | 定数式の文脈での配置`new`を許可 | | | | | diff --git a/lang/cpp26.md b/lang/cpp26.md index a352f35065..0171014cf1 100644 --- a/lang/cpp26.md +++ b/lang/cpp26.md @@ -17,7 +17,7 @@ C++26とは、2026年中に改訂される予定の、C++バージョンの通 | [不完全型へのポインタに対する`delete`を不適格とする](/lang/cpp26/deleting_a_pointer_to_an_incomplete_type_should_be_ill-formed.md.nolink) | 未定義動作となる操作をコンパイルエラーとする | | [返却された左辺値から暗黙変換された一時オブジェクトが参照に束縛されることを禁止する](/lang/cpp26/disallow_binding_a_returned_glvalue_to_a_temporary.md.nolink) | 寿命切れの変数によって引き起こされるバグを防止する | | [要素数不明の配列を集成体初期化する規則を明確化](/lang/cpp26/clarifying_rules_for_brace_elision_in_aggregate_initialization.md.nolink) | 配列要素の集成体初期化で`{}`が省略された場合の矛盾していた規定を修正 | -| [未初期化変数の読み取りを不正動作 (erroneous behaviour: EB) とする](/lang/cpp26/erroneous_behaviour_for_uninitialized_reads.md.nolink) | 初期化されていない自動変数の読み取りの安全性を規定する | +| [未初期化変数の読み取りを誤り起因動作とする](/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md) | 初期化されていない自動変数の読み取りの安全性を規定する | ### 文字列 diff --git a/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md b/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md new file mode 100644 index 0000000000..75c6935996 --- /dev/null +++ b/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md @@ -0,0 +1,121 @@ +# 未初期化変数の読み取りを誤り起因動作とする [P2795R5] +* cpp26[meta cpp] + + + +このページはC++26に採用される見込みの言語機能の変更を解説しています。 + +のちのC++規格でさらに変更される場合があるため[関連項目](#relative-page)を参照してください。 + + + +## 概要 +これまで、未初期化変数 (デフォルト初期化された変数) の読み取りは未定義動作として扱われていた。C++26では、この操作が安全上のリスクをもたらさないものとして、「誤り起因動作 (erroneous behavior; 通称 EB)」を新設してそれに割り当てることとした。 + +この変更の対象は、デフォルト初期化されたスカラ型 (`void`以外の組み込み型) 変数の読み取りであり、以下のようなケースである。 + +```cpp +// C++23 +void f(int); + +int main() { + int x; // デフォルト初期化。xは不定値 (indeterminate value) をもつ + f(x); // 左辺値から右辺値への変換が未定義動作を引き起こす +} +``` + +未初期化の値は、コンパイラやターゲット環境によって定義された固定値である。コンパイラにはこの誤りを診断することが許可され、推奨されているが、誤りを無視して有効な読み取りとして扱うことも許可されている。このコードは誤りではあるが、未定義動作に関連する結果に遭遇するリスクはない。 + +誤り起因動作は未定義動作とはちがって、明確に定義された動作をするがコードとして正しくない、ということを規定するものであり、処理系に対して有用な診断を提供するものである。 + +C++26では、不定値で初期化されることを明確に指示する`[[indeterminate]]`属性も導入され、以下のような動作となる: + +```cpp +// C++26 +void f(int); + +int main() { + int x; // xは誤り起因動作を引き起こす未初期化値をもつ + int y [[indeterminate]]; // 意図して不定値に初期化されることを指示 + + f(x); // 誤り起因動作 (未初期化値の読み取り) + f(y); // 未定義動作 (不定値の読み取り) +} +``` + + +## 仕様 +- 式が評価された結果として不定値が生成された場合、未定義動作を引き起こす +- 式が評価された結果として未初期化値が生成された場合、誤り起因動作を引き起こす + - ただし、`unsigned char`もしくは[`std::byte`](/reference/cstddef/byte.md)型に関しては、未初期化値をもつ変数を同じ型の変数に代入するだけでは誤り起因動作にならず、値の参照や型変換がされることで誤り起因動作を引き起こす +- 誤り起因動作が引き起こされた結果値は、後続の処理では誤り起因動作を引き起こす値とはみなされない + +```cpp +int g(bool b) { + unsigned char c; + unsigned char d = c; // 誤り起因動作ではない。dは誤り起因動作を引き起こす未初期化値をもつ + + assert(c == d); // どちらの変数も整数昇格され誤り起因動作となる + + int e = d; // 誤り起因動作 (型変換) + return b ? d : 0; // bがtrueの場合に誤り起因動作 +} + +void h() { + int d1, d2; + + int e1 = d1; // 誤り起因動作 + int e2 = d1; // 誤り起因動作 + + // 処理が続行した場合… + assert(e1 == e2); // OK。誤り起因動作の結果で生成された値は正常 + assert(e1 == d1); // 誤り起因動作 + assert(e2 == d1); // 誤り起因動作 + + // 誤り起因動作ではないが + // d2は誤り起因動作を引き起こす未初期化値をもつ + std::memcpy(&d2, &d1, sizeof(int)); + + assert(e1 == d2); // 誤り起因動作 + assert(e2 == d2); // 誤り起因動作 +} +``` + +### `[[indeterminate]]`属性 +`[[indeterminate]]`属性は、自動変数が初期状態として意図して不定値をもつことを指示するものであり、自動変数の定義、もしくは関数のパラメータ宣言に適用できる。 + +関数のパラメータが`[[indeterminate]]`属性で宣言される場合、その関数の最初の宣言でそのように宣言されなければならない (注:関数宣言は複数行うことができるが、その最初の宣言で`[[indeterminate]]`属性をつけなければならない)。 + +`[[indeterminate]]`がつけられた変数から読み取りをした場合、未定義動作を引き起こす可能性がある。 + +```cpp +struct T { + T() {} + int x; +}; + +int h(T t [[indeterminate]]) { + f(t.x); // この関数呼び出しは未定義動作を引き起こす + return 0; +} +int _ = h(T()); +``` + +### 今後、誤り起因動作に分類される可能性のある操作 + +現在、未定義動作に分類される以下の操作は、誤り起因動作に分類できる可能性がある。 + +| 操作 | 備考 | +|------|------| +| 符号付き整数のオーバーフロー | 演算結果としてオーバーフローした場合に誤った結果になる可能性がある。これは珍しいバグではない。これは安全上の大きな問題ではない | +| 算術型の変換結果としてその型の表現可能な範囲を超えた | 符号付き整数のオーバーフローと同じ | +| 誤ったビットシフト (負のシフト幅や、上限を超えたシフト幅) | 符号付き整数のオーバーフローと同じ | +| ゼロ割り | いくつかの固定値での誤った結果となる可能性がある。影響が不明確であるため、変更にはコストがかかる | +| 戻り値型が非`void`な関数から返った、もしくは`[[noreturn]]`属性をつけた関数から返った | [`std::terminate()`](/reference/exception/terminate.md)が呼ばれる可能性がある。変更には軽いコストがかかるが、その変更にどの程度の価値があるかは不明 | +| 抽象クラスのコンストラクタ・デストラクタからの純粋仮想関数の呼び出し | 特定の純粋仮想ハンドラが呼ばれる可能性がある。実装によってはすでに誤り起因動作のように扱われている可能性がある | +| 契約違反 | 契約に関する現在の策定作業では、契約違反時になにが起こるべきかという問題に直面している。誤り起因動作という概念は有用な回答を与えてくれる可能性がある | + + + +## 参照 +- [P2795R5 Erroneous behaviour for uninitialized reads](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2795r5.html) From cd6d39bd32c3a28bdbf4645a884f8c2406da16f0 Mon Sep 17 00:00:00 2001 From: Akira Takahashi Date: Tue, 17 Sep 2024 16:14:43 +0900 Subject: [PATCH 02/21] =?UTF-8?q?C++26=20=E6=9C=AA=E5=88=9D=E6=9C=9F?= =?UTF-8?q?=E5=8C=96=E5=A4=89=E6=95=B0=E3=81=AE=E8=AA=AD=E3=81=BF=E5=8F=96?= =?UTF-8?q?=E3=82=8A=20:=20erroneous=20behavior=E5=BE=8C=E3=81=AE=E7=B5=90?= =?UTF-8?q?=E6=9E=9C=E5=80=A4=E3=81=AB=E9=96=A2=E3=81=99=E3=82=8B=E8=AA=AC?= =?UTF-8?q?=E6=98=8E=E3=82=92=E6=95=B4=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../erroneous_behavior_for_uninitialized_reads.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md b/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md index 75c6935996..6f57d8887c 100644 --- a/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md +++ b/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md @@ -64,13 +64,14 @@ int g(bool b) { void h() { int d1, d2; - int e1 = d1; // 誤り起因動作 - int e2 = d1; // 誤り起因動作 + int e1 = d1; // 誤り起因動作 + int e2 = d1; // 誤り起因動作 // 処理が続行した場合… - assert(e1 == e2); // OK。誤り起因動作の結果で生成された値は正常 - assert(e1 == d1); // 誤り起因動作 - assert(e2 == d1); // 誤り起因動作 + assert(e1 == e2); // OK。誤り起因動作の結果で生成された値 (e1とe2) は、 + // 誤り起因動作を引き起こす値とはみなされない + assert(e1 == d1); // 誤り起因動作 + assert(e2 == d1); // 誤り起因動作 // 誤り起因動作ではないが // d2は誤り起因動作を引き起こす未初期化値をもつ From 040c50993c98a6e20e9a3156f74ec4a29c50f42b Mon Sep 17 00:00:00 2001 From: Akira Takahashi Date: Tue, 17 Sep 2024 16:16:12 +0900 Subject: [PATCH 03/21] =?UTF-8?q?C++26=20=E6=9C=AA=E5=88=9D=E6=9C=9F?= =?UTF-8?q?=E5=8C=96=E5=A4=89=E6=95=B0=E3=81=AE=E8=AA=AD=E3=81=BF=E5=8F=96?= =?UTF-8?q?=E3=82=8A=20:=20=E3=82=B3=E3=83=BC=E3=83=89=E4=BE=8B=E3=81=ABex?= =?UTF-8?q?ample=E3=82=92=E3=81=A4=E3=81=91=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...oneous_behavior_for_uninitialized_reads.md | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md b/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md index 6f57d8887c..986d325010 100644 --- a/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md +++ b/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md @@ -14,9 +14,9 @@ この変更の対象は、デフォルト初期化されたスカラ型 (`void`以外の組み込み型) 変数の読み取りであり、以下のようなケースである。 -```cpp +```cpp example // C++23 -void f(int); +void f(int) {} int main() { int x; // デフォルト初期化。xは不定値 (indeterminate value) をもつ @@ -30,9 +30,9 @@ int main() { C++26では、不定値で初期化されることを明確に指示する`[[indeterminate]]`属性も導入され、以下のような動作となる: -```cpp +```cpp example // C++26 -void f(int); +void f(int) {} int main() { int x; // xは誤り起因動作を引き起こす未初期化値をもつ @@ -50,7 +50,9 @@ int main() { - ただし、`unsigned char`もしくは[`std::byte`](/reference/cstddef/byte.md)型に関しては、未初期化値をもつ変数を同じ型の変数に代入するだけでは誤り起因動作にならず、値の参照や型変換がされることで誤り起因動作を引き起こす - 誤り起因動作が引き起こされた結果値は、後続の処理では誤り起因動作を引き起こす値とはみなされない -```cpp +```cpp example +#include + int g(bool b) { unsigned char c; unsigned char d = c; // 誤り起因動作ではない。dは誤り起因動作を引き起こす未初期化値をもつ @@ -61,7 +63,7 @@ int g(bool b) { return b ? d : 0; // bがtrueの場合に誤り起因動作 } -void h() { +int main() { int d1, d2; int e1 = d1; // 誤り起因動作 @@ -89,7 +91,7 @@ void h() { `[[indeterminate]]`がつけられた変数から読み取りをした場合、未定義動作を引き起こす可能性がある。 -```cpp +```cpp example struct T { T() {} int x; @@ -99,7 +101,10 @@ int h(T t [[indeterminate]]) { f(t.x); // この関数呼び出しは未定義動作を引き起こす return 0; } -int _ = h(T()); + +int main() { + int _ = h(T()); +} ``` ### 今後、誤り起因動作に分類される可能性のある操作 From a11497563df78a1a84fb734aaa2dbe77bb29587f Mon Sep 17 00:00:00 2001 From: Akira Takahashi Date: Mon, 30 Sep 2024 17:29:42 +0900 Subject: [PATCH 04/21] =?UTF-8?q?=E7=94=A8=E8=AA=9E=E5=AE=9A=E7=BE=A9=20:?= =?UTF-8?q?=20erroneous=20behavior=E3=81=AE=E6=A6=82=E8=A6=81=E3=82=92?= =?UTF-8?q?=E5=AE=9F=E6=85=8B=E3=81=AB=E5=90=88=E3=81=86=E3=82=88=E3=81=86?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kazutoshi SATODA --- GLOBAL_DEFINED_WORDS.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GLOBAL_DEFINED_WORDS.json b/GLOBAL_DEFINED_WORDS.json index c87f83a9d2..2cbc13a804 100644 --- a/GLOBAL_DEFINED_WORDS.json +++ b/GLOBAL_DEFINED_WORDS.json @@ -25,7 +25,7 @@ "未規定": { "redirect": "未規定の動作", "yomi": "みきてい" }, "誤り起因動作": { "yomi": "あやまりきいんどうさ", - "desc": "誤った操作に対する結果が明確に定義された動作。erroneous behavior (EB)。処理系によって診断や異常終了を実行することが許可されるが、処理が続行する場合もある" + "desc": "未定義動作ではないが、誤ったプログラムの結果とされる動作。erroneous behavior (EB)。処理系によって診断や異常終了を実行することが許可されるが、処理が続行する場合もある" }, "処理系定義の動作": { "link": "/implementation-compliance.md#dfn-implementation-defined-behavior", From 7f7759e676d1db0ca5e663937e8e71562a514ecc Mon Sep 17 00:00:00 2001 From: Akira Takahashi Date: Mon, 30 Sep 2024 17:30:34 +0900 Subject: [PATCH 05/21] =?UTF-8?q?C++26=20=E6=9C=AA=E5=88=9D=E6=9C=9F?= =?UTF-8?q?=E5=8C=96=E5=A4=89=E6=95=B0=E3=81=AE=E8=AA=AD=E3=81=BF=E5=8F=96?= =?UTF-8?q?=E3=82=8A=20:=20=E6=A6=82=E8=A6=81=E3=82=92=E6=95=B4=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kazutoshi SATODA --- lang/cpp26/erroneous_behavior_for_uninitialized_reads.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md b/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md index 986d325010..b373cd622c 100644 --- a/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md +++ b/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md @@ -10,7 +10,7 @@ ## 概要 -これまで、未初期化変数 (デフォルト初期化された変数) の読み取りは未定義動作として扱われていた。C++26では、この操作が安全上のリスクをもたらさないものとして、「誤り起因動作 (erroneous behavior; 通称 EB)」を新設してそれに割り当てることとした。 +C++23までは、未初期化変数 (デフォルト初期化された変数) の読み取りは未定義動作として扱われていた。C++26では、この未定義動作による安全上のリスクを低減するため、「誤り起因動作 (erroneous behavior; 通称 EB)」を新設してその多くに割り当てることとした。 この変更の対象は、デフォルト初期化されたスカラ型 (`void`以外の組み込み型) 変数の読み取りであり、以下のようなケースである。 From 6b0e3d7c690889610c9d07cf855155cc44140091 Mon Sep 17 00:00:00 2001 From: Akira Takahashi Date: Mon, 30 Sep 2024 17:39:10 +0900 Subject: [PATCH 06/21] =?UTF-8?q?C++26=20=E6=9C=AA=E5=88=9D=E6=9C=9F?= =?UTF-8?q?=E5=8C=96=E5=A4=89=E6=95=B0=E3=81=AE=E8=AA=AD=E3=81=BF=E5=8F=96?= =?UTF-8?q?=E3=82=8A=20:=20assert=E7=B5=90=E6=9E=9C=E3=82=92=E6=98=8E?= =?UTF-8?q?=E8=A8=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lang/cpp26/erroneous_behavior_for_uninitialized_reads.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md b/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md index b373cd622c..9f8b11274c 100644 --- a/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md +++ b/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md @@ -57,7 +57,7 @@ int g(bool b) { unsigned char c; unsigned char d = c; // 誤り起因動作ではない。dは誤り起因動作を引き起こす未初期化値をもつ - assert(c == d); // どちらの変数も整数昇格され誤り起因動作となる + assert(c == d); // 常に真、誤り起因動作 (整数昇格) int e = d; // 誤り起因動作 (型変換) return b ? d : 0; // bがtrueの場合に誤り起因動作 @@ -70,10 +70,11 @@ int main() { int e2 = d1; // 誤り起因動作 // 処理が続行した場合… - assert(e1 == e2); // OK。誤り起因動作の結果で生成された値 (e1とe2) は、 + assert(e1 == e2); // 常に真、誤り起因動作ではない。 + // 誤り起因動作の結果で生成された値 (e1とe2) は、 // 誤り起因動作を引き起こす値とはみなされない - assert(e1 == d1); // 誤り起因動作 - assert(e2 == d1); // 誤り起因動作 + assert(e1 == d1); // 常に真、誤り起因動作 + assert(e2 == d1); // 常に真、誤り起因動作 // 誤り起因動作ではないが // d2は誤り起因動作を引き起こす未初期化値をもつ From 2a4fe0e98448cff506fa43ef922ab2e4e44ec9ba Mon Sep 17 00:00:00 2001 From: Akira Takahashi Date: Mon, 30 Sep 2024 17:50:56 +0900 Subject: [PATCH 07/21] =?UTF-8?q?C++26=20=E6=9C=AA=E5=88=9D=E6=9C=9F?= =?UTF-8?q?=E5=8C=96=E5=A4=89=E6=95=B0=E3=81=AE=E8=AA=AD=E3=81=BF=E5=8F=96?= =?UTF-8?q?=E3=82=8A=20:=20=E5=8B=95=E7=9A=84=E7=A2=BA=E4=BF=9D=E3=81=95?= =?UTF-8?q?=E3=82=8C=E3=81=9F=E3=82=AA=E3=83=96=E3=82=B8=E3=82=A7=E3=82=AF?= =?UTF-8?q?=E3=83=88=E3=81=8C=E5=AF=BE=E8=B1=A1=E5=A4=96=E3=81=A7=E3=81=82?= =?UTF-8?q?=E3=82=8B=E3=81=93=E3=81=A8=E3=82=92=E8=A8=98=E8=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lang/cpp26/erroneous_behavior_for_uninitialized_reads.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md b/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md index 9f8b11274c..76c953600e 100644 --- a/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md +++ b/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md @@ -12,8 +12,6 @@ ## 概要 C++23までは、未初期化変数 (デフォルト初期化された変数) の読み取りは未定義動作として扱われていた。C++26では、この未定義動作による安全上のリスクを低減するため、「誤り起因動作 (erroneous behavior; 通称 EB)」を新設してその多くに割り当てることとした。 -この変更の対象は、デフォルト初期化されたスカラ型 (`void`以外の組み込み型) 変数の読み取りであり、以下のようなケースである。 - ```cpp example // C++23 void f(int) {} @@ -47,7 +45,10 @@ int main() { ## 仕様 - 式が評価された結果として不定値が生成された場合、未定義動作を引き起こす - 式が評価された結果として未初期化値が生成された場合、誤り起因動作を引き起こす - - ただし、`unsigned char`もしくは[`std::byte`](/reference/cstddef/byte.md)型に関しては、未初期化値をもつ変数を同じ型の変数に代入するだけでは誤り起因動作にならず、値の参照や型変換がされることで誤り起因動作を引き起こす + - 未初期価値が生成されることで誤り起因動作を引き起こす対象は以下: + - 自動記憶域期間をもつオブジェクトのうち、`void`以外のスカラ型 + - 注意 : 動的記憶域期間をもつオブジェクトは対象外 + - ただし、`unsigned char`もしくは[`std::byte`](/reference/cstddef/byte.md)型に関しては、未初期化値をもつ変数を同じ型の変数に代入するだけでは誤り起因動作にならず、値の参照や型変換がされることで誤り起因動作を引き起こす - 誤り起因動作が引き起こされた結果値は、後続の処理では誤り起因動作を引き起こす値とはみなされない ```cpp example From 30cfb4e7851be5968e72953fad20763f8321bd74 Mon Sep 17 00:00:00 2001 From: Akira Takahashi Date: Mon, 7 Oct 2024 17:26:20 +0900 Subject: [PATCH 08/21] =?UTF-8?q?erroneous=20behavior/value=E3=82=92?= =?UTF-8?q?=E4=B8=80=E6=97=A6=E8=A8=B3=E3=81=95=E3=81=AA=E3=81=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- GLOBAL_DEFINED_WORDS.json | 4 +- implementation-status.md | 2 +- lang/cpp26.md | 2 +- ...oneous_behavior_for_uninitialized_reads.md | 58 +++++++++---------- 4 files changed, 33 insertions(+), 33 deletions(-) diff --git a/GLOBAL_DEFINED_WORDS.json b/GLOBAL_DEFINED_WORDS.json index 2cbc13a804..f78301d146 100644 --- a/GLOBAL_DEFINED_WORDS.json +++ b/GLOBAL_DEFINED_WORDS.json @@ -23,8 +23,8 @@ }, "未規定動作": { "redirect": "未規定の動作", "yomi": "みきていどうさ" }, "未規定": { "redirect": "未規定の動作", "yomi": "みきてい" }, - "誤り起因動作": { - "yomi": "あやまりきいんどうさ", + "「erroneous behavior」": { + "yomi": "えらーなうすべへいびあ", "desc": "未定義動作ではないが、誤ったプログラムの結果とされる動作。erroneous behavior (EB)。処理系によって診断や異常終了を実行することが許可されるが、処理が続行する場合もある" }, "処理系定義の動作": { diff --git a/implementation-status.md b/implementation-status.md index d26f038dc0..7efadc50eb 100644 --- a/implementation-status.md +++ b/implementation-status.md @@ -305,7 +305,7 @@ | P0609R3: [構造化束縛への属性を許可](/lang/cpp26/attributes_for_structured_bindings.md) | `auto [a, b [[maybe_unused]], c] = f();`のように構造化束縛の要素に対して属性を付加できるようにする | 15 | 19 | | | | P3034R1: [モジュール宣言でのモジュール名のマクロ展開を禁止する](/lang/cpp26/module_declarations_shouldnt_be_macros.md.nolink) | `export module MACRO_NAME;`を禁止 | | | | | | P2809R3: [自明な無限ループは未定義動作ではないと規定](/lang/cpp26/trivial_infinite_loops_are_not_undefined_behavior.md.nolink) | 並行プログラムの進行保証などを考慮して無限ループを未定義動作ではないものとする | 14 | 19 | | | -| P2795R5: [未初期化変数の読み取りを誤り起因動作とする](/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md) | 初期化されていない自動変数の読み取りの安全性を規定する | | | | | +| P2795R5: [未初期化変数の読み取りを"erroneous behavior"とする](/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md) | 初期化されていない自動変数の読み取りの安全性を規定する | | | | | | P2573R2: [関数宣言を削除する理由を指定できるようにする](/lang/cpp26/delete_reason.md) | `f() = delete("reason");` | 15 | 19 | | | | P2893R3: [可変引数テンプレートで`friend`宣言をできるようにする](/lang/cpp26/variadic_friends.md.nolink) | クラステンプレートの可変引数テンプレートでまとめて`friend`宣言できるようにする | 15 | | | | | P2747R2: [`constexpr`配置`new`](/lang/cpp26/constexpr_placement_new.md.nolink) | 定数式の文脈での配置`new`を許可 | | | | | diff --git a/lang/cpp26.md b/lang/cpp26.md index 0171014cf1..fff209b541 100644 --- a/lang/cpp26.md +++ b/lang/cpp26.md @@ -17,7 +17,7 @@ C++26とは、2026年中に改訂される予定の、C++バージョンの通 | [不完全型へのポインタに対する`delete`を不適格とする](/lang/cpp26/deleting_a_pointer_to_an_incomplete_type_should_be_ill-formed.md.nolink) | 未定義動作となる操作をコンパイルエラーとする | | [返却された左辺値から暗黙変換された一時オブジェクトが参照に束縛されることを禁止する](/lang/cpp26/disallow_binding_a_returned_glvalue_to_a_temporary.md.nolink) | 寿命切れの変数によって引き起こされるバグを防止する | | [要素数不明の配列を集成体初期化する規則を明確化](/lang/cpp26/clarifying_rules_for_brace_elision_in_aggregate_initialization.md.nolink) | 配列要素の集成体初期化で`{}`が省略された場合の矛盾していた規定を修正 | -| [未初期化変数の読み取りを誤り起因動作とする](/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md) | 初期化されていない自動変数の読み取りの安全性を規定する | +| [未初期化変数の読み取りを「erroneous behavior」とする](/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md) | 初期化されていない自動変数の読み取りの安全性を規定する | ### 文字列 diff --git a/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md b/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md index 76c953600e..70c3141bb2 100644 --- a/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md +++ b/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md @@ -1,4 +1,4 @@ -# 未初期化変数の読み取りを誤り起因動作とする [P2795R5] +# 未初期化変数の読み取りを「erroneous behavior」とする [P2795R5] * cpp26[meta cpp] @@ -10,7 +10,7 @@ ## 概要 -C++23までは、未初期化変数 (デフォルト初期化された変数) の読み取りは未定義動作として扱われていた。C++26では、この未定義動作による安全上のリスクを低減するため、「誤り起因動作 (erroneous behavior; 通称 EB)」を新設してその多くに割り当てることとした。 +C++23までは、未初期化変数 (デフォルト初期化された変数) の読み取りは未定義動作として扱われていた。C++26では、この未定義動作による安全上のリスクを低減するため、「「erroneous behavior」 (erroneous behavior; 通称 EB)」を新設してその多くに割り当てることとした。 ```cpp example // C++23 @@ -24,7 +24,7 @@ int main() { 未初期化の値は、コンパイラやターゲット環境によって定義された固定値である。コンパイラにはこの誤りを診断することが許可され、推奨されているが、誤りを無視して有効な読み取りとして扱うことも許可されている。このコードは誤りではあるが、未定義動作に関連する結果に遭遇するリスクはない。 -誤り起因動作は未定義動作とはちがって、明確に定義された動作をするがコードとして正しくない、ということを規定するものであり、処理系に対して有用な診断を提供するものである。 +「erroneous behavior」は未定義動作とはちがって、明確に定義された動作をするがコードとして正しくない、ということを規定するものであり、処理系に対して有用な診断を提供するものである。 C++26では、不定値で初期化されることを明確に指示する`[[indeterminate]]`属性も導入され、以下のような動作となる: @@ -33,10 +33,10 @@ C++26では、不定値で初期化されることを明確に指示する`[[ind void f(int) {} int main() { - int x; // xは誤り起因動作を引き起こす未初期化値をもつ + int x; // xは「erroneous value」をもつ int y [[indeterminate]]; // 意図して不定値に初期化されることを指示 - f(x); // 誤り起因動作 (未初期化値の読み取り) + f(x); // erroneous behavior (未初期化値の読み取り) f(y); // 未定義動作 (不定値の読み取り) } ``` @@ -44,45 +44,45 @@ int main() { ## 仕様 - 式が評価された結果として不定値が生成された場合、未定義動作を引き起こす -- 式が評価された結果として未初期化値が生成された場合、誤り起因動作を引き起こす - - 未初期価値が生成されることで誤り起因動作を引き起こす対象は以下: +- 式が評価された結果として未初期化値が生成された場合、「erroneous behavior」を引き起こす + - 未初期価値が生成されることで「erroneous behavior」を引き起こす対象は以下: - 自動記憶域期間をもつオブジェクトのうち、`void`以外のスカラ型 - 注意 : 動的記憶域期間をもつオブジェクトは対象外 - - ただし、`unsigned char`もしくは[`std::byte`](/reference/cstddef/byte.md)型に関しては、未初期化値をもつ変数を同じ型の変数に代入するだけでは誤り起因動作にならず、値の参照や型変換がされることで誤り起因動作を引き起こす -- 誤り起因動作が引き起こされた結果値は、後続の処理では誤り起因動作を引き起こす値とはみなされない + - ただし、`unsigned char`もしくは[`std::byte`](/reference/cstddef/byte.md)型に関しては、未初期化値をもつ変数を同じ型の変数に代入するだけでは「erroneous behavior」にならず、値の参照や型変換がされることで「erroneous behavior」を引き起こす +- 「erroneous behavior」が引き起こされた結果値は、後続の処理では「erroneous value」とはみなされない ```cpp example #include int g(bool b) { unsigned char c; - unsigned char d = c; // 誤り起因動作ではない。dは誤り起因動作を引き起こす未初期化値をもつ + unsigned char d = c; // 「erroneous behavior」ではない。dは「erroneous value」をもつ - assert(c == d); // 常に真、誤り起因動作 (整数昇格) + assert(c == d); // 常に真、「erroneous behavior」 (整数昇格) - int e = d; // 誤り起因動作 (型変換) - return b ? d : 0; // bがtrueの場合に誤り起因動作 + int e = d; // 「erroneous behavior」 (型変換) + return b ? d : 0; // bがtrueの場合に「erroneous behavior」 } int main() { int d1, d2; - int e1 = d1; // 誤り起因動作 - int e2 = d1; // 誤り起因動作 + int e1 = d1; // 「erroneous behavior」 + int e2 = d1; // 「erroneous behavior」 // 処理が続行した場合… - assert(e1 == e2); // 常に真、誤り起因動作ではない。 - // 誤り起因動作の結果で生成された値 (e1とe2) は、 - // 誤り起因動作を引き起こす値とはみなされない - assert(e1 == d1); // 常に真、誤り起因動作 - assert(e2 == d1); // 常に真、誤り起因動作 - - // 誤り起因動作ではないが - // d2は誤り起因動作を引き起こす未初期化値をもつ + assert(e1 == e2); // 常に真、「erroneous behavior」ではない。 + // 「erroneous behavior」の結果で生成された値 (e1とe2) は、 + // 「erroneous value」とはみなされない + assert(e1 == d1); // 常に真、「erroneous behavior」 + assert(e2 == d1); // 常に真、「erroneous behavior」 + + // 「erroneous behavior」ではないが + // d2は「erroneous value」をもつ std::memcpy(&d2, &d1, sizeof(int)); - assert(e1 == d2); // 誤り起因動作 - assert(e2 == d2); // 誤り起因動作 + assert(e1 == d2); // 「erroneous behavior」 + assert(e2 == d2); // 「erroneous behavior」 } ``` @@ -109,9 +109,9 @@ int main() { } ``` -### 今後、誤り起因動作に分類される可能性のある操作 +### 今後、「erroneous behavior」に分類される可能性のある操作 -現在、未定義動作に分類される以下の操作は、誤り起因動作に分類できる可能性がある。 +現在、未定義動作に分類される以下の操作は、「erroneous behavior」に分類できる可能性がある。 | 操作 | 備考 | |------|------| @@ -120,8 +120,8 @@ int main() { | 誤ったビットシフト (負のシフト幅や、上限を超えたシフト幅) | 符号付き整数のオーバーフローと同じ | | ゼロ割り | いくつかの固定値での誤った結果となる可能性がある。影響が不明確であるため、変更にはコストがかかる | | 戻り値型が非`void`な関数から返った、もしくは`[[noreturn]]`属性をつけた関数から返った | [`std::terminate()`](/reference/exception/terminate.md)が呼ばれる可能性がある。変更には軽いコストがかかるが、その変更にどの程度の価値があるかは不明 | -| 抽象クラスのコンストラクタ・デストラクタからの純粋仮想関数の呼び出し | 特定の純粋仮想ハンドラが呼ばれる可能性がある。実装によってはすでに誤り起因動作のように扱われている可能性がある | -| 契約違反 | 契約に関する現在の策定作業では、契約違反時になにが起こるべきかという問題に直面している。誤り起因動作という概念は有用な回答を与えてくれる可能性がある | +| 抽象クラスのコンストラクタ・デストラクタからの純粋仮想関数の呼び出し | 特定の純粋仮想ハンドラが呼ばれる可能性がある。実装によってはすでに「erroneous behavior」のように扱われている可能性がある | +| 契約違反 | 契約に関する現在の策定作業では、契約違反時になにが起こるべきかという問題に直面している。「erroneous behavior」という概念は有用な回答を与えてくれる可能性がある | From 7d2188d349fa4087b9994ebdb29bd58d2b05170f Mon Sep 17 00:00:00 2001 From: Akira Takahashi Date: Mon, 7 Oct 2024 17:39:21 +0900 Subject: [PATCH 09/21] =?UTF-8?q?C++26=20=E6=9C=AA=E5=88=9D=E6=9C=9F?= =?UTF-8?q?=E5=8C=96=E5=80=A4=E3=81=AE=E8=AA=AD=E3=81=BF=E5=8F=96=E3=82=8A?= =?UTF-8?q?=20:=20=E6=9C=AA=E5=AE=9A=E7=BE=A9=E5=8B=95=E4=BD=9C=E3=81=AB?= =?UTF-8?q?=E3=81=AA=E3=82=8A=E3=81=88=E3=82=8B=E3=82=B1=E3=83=BC=E3=82=B9?= =?UTF-8?q?=E3=82=92=E8=A8=98=E8=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../erroneous_behavior_for_uninitialized_reads.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md b/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md index 70c3141bb2..c90685a234 100644 --- a/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md +++ b/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md @@ -22,7 +22,7 @@ int main() { } ``` -未初期化の値は、コンパイラやターゲット環境によって定義された固定値である。コンパイラにはこの誤りを診断することが許可され、推奨されているが、誤りを無視して有効な読み取りとして扱うことも許可されている。このコードは誤りではあるが、未定義動作に関連する結果に遭遇するリスクはない。 +未初期化の値は、コンパイラやターゲット環境によって定義された固定値である。コンパイラにはこの誤りを診断することが許可され、推奨されているが、誤りを無視して有効な読み取りとして扱うことも許可されている。このコードは誤りではあるが、実行ごとに異なる動作をしたり攻撃者に値を制御されたりといったリスクはなくなる。 「erroneous behavior」は未定義動作とはちがって、明確に定義された動作をするがコードとして正しくない、ということを規定するものであり、処理系に対して有用な診断を提供するものである。 @@ -124,6 +124,17 @@ int main() { | 契約違反 | 契約に関する現在の策定作業では、契約違反時になにが起こるべきかという問題に直面している。「erroneous behavior」という概念は有用な回答を与えてくれる可能性がある | +## 備考 +- 以下のようなケースでは、erroneous behaviorではなく未定義動作を引き起こす可能性がある: + ```cpp + T* p; // 未初期化のポインタ。erroneous value (例としてヌルポインタ) をもつ + bool b; // 未初期化の真理値。erroneous valueとして、 + // 妥当ではないbool値 (trueでもfalseでもない値) をもつ可能性がある + + f(*p); // 間接参照は未定義動作を引き起こす + g(b); // bが妥当な値である場合にerroneous behavior、そうでなければ未定義動作 + ``` + ## 参照 - [P2795R5 Erroneous behaviour for uninitialized reads](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2795r5.html) From c965e2646205ce6bb09d44cbcdf4906099d4e4d7 Mon Sep 17 00:00:00 2001 From: Akira Takahashi Date: Tue, 8 Oct 2024 13:39:09 +0900 Subject: [PATCH 10/21] =?UTF-8?q?=E7=94=A8=E8=AA=9E=20:=20=E8=AA=AD?= =?UTF-8?q?=E3=81=BF=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kazutoshi SATODA --- GLOBAL_DEFINED_WORDS.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GLOBAL_DEFINED_WORDS.json b/GLOBAL_DEFINED_WORDS.json index f78301d146..8202b750d7 100644 --- a/GLOBAL_DEFINED_WORDS.json +++ b/GLOBAL_DEFINED_WORDS.json @@ -24,7 +24,7 @@ "未規定動作": { "redirect": "未規定の動作", "yomi": "みきていどうさ" }, "未規定": { "redirect": "未規定の動作", "yomi": "みきてい" }, "「erroneous behavior」": { - "yomi": "えらーなうすべへいびあ", + "yomi": "えろーにあすびへいびあ", "desc": "未定義動作ではないが、誤ったプログラムの結果とされる動作。erroneous behavior (EB)。処理系によって診断や異常終了を実行することが許可されるが、処理が続行する場合もある" }, "処理系定義の動作": { From 7e6827164ad394ff8756a9ce1d89410d24cb41c1 Mon Sep 17 00:00:00 2001 From: Akira Takahashi Date: Tue, 8 Oct 2024 13:39:44 +0900 Subject: [PATCH 11/21] =?UTF-8?q?C++26=20=E6=9C=AA=E5=88=9D=E6=9C=9F?= =?UTF-8?q?=E5=8C=96=E5=A4=89=E6=95=B0=E3=81=AE=E8=AA=AD=E3=81=BF=E5=8F=96?= =?UTF-8?q?=E3=82=8A=20:=20=E8=A8=B3=E3=81=97=E3=81=A6=E3=81=AA=E3=81=84?= =?UTF-8?q?=E7=94=A8=E8=AA=9E=E3=81=AE=E3=83=9E=E3=83=BC=E3=82=AD=E3=83=B3?= =?UTF-8?q?=E3=82=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kazutoshi SATODA --- lang/cpp26/erroneous_behavior_for_uninitialized_reads.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md b/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md index c90685a234..0c394ef7cc 100644 --- a/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md +++ b/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md @@ -36,7 +36,7 @@ int main() { int x; // xは「erroneous value」をもつ int y [[indeterminate]]; // 意図して不定値に初期化されることを指示 - f(x); // erroneous behavior (未初期化値の読み取り) + f(x); // 「erroneous behavior」 (「erroneous value」の読み取り) f(y); // 未定義動作 (不定値の読み取り) } ``` From aeee953c0c7ae6b10bdcfb2514689af557f20c90 Mon Sep 17 00:00:00 2001 From: Akira Takahashi Date: Tue, 8 Oct 2024 13:40:55 +0900 Subject: [PATCH 12/21] =?UTF-8?q?C++26=20=E6=9C=AA=E5=88=9D=E6=9C=9F?= =?UTF-8?q?=E5=8C=96=E5=A4=89=E6=95=B0=E3=81=AE=E8=AA=AD=E3=81=BF=E5=8F=96?= =?UTF-8?q?=E3=82=8A=20:=20=E4=BB=95=E6=A7=98=E8=AA=AC=E6=98=8E=E3=82=92?= =?UTF-8?q?=E8=A6=8B=E7=9B=B4=E3=81=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kazutoshi SATODA --- .../erroneous_behavior_for_uninitialized_reads.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md b/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md index 0c394ef7cc..36e00c8832 100644 --- a/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md +++ b/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md @@ -43,13 +43,13 @@ int main() { ## 仕様 -- 式が評価された結果として不定値が生成された場合、未定義動作を引き起こす -- 式が評価された結果として未初期化値が生成された場合、「erroneous behavior」を引き起こす - - 未初期価値が生成されることで「erroneous behavior」を引き起こす対象は以下: - - 自動記憶域期間をもつオブジェクトのうち、`void`以外のスカラ型 - - 注意 : 動的記憶域期間をもつオブジェクトは対象外 - - ただし、`unsigned char`もしくは[`std::byte`](/reference/cstddef/byte.md)型に関しては、未初期化値をもつ変数を同じ型の変数に代入するだけでは「erroneous behavior」にならず、値の参照や型変換がされることで「erroneous behavior」を引き起こす -- 「erroneous behavior」が引き起こされた結果値は、後続の処理では「erroneous value」とはみなされない +- 自動記憶域期間をもつオブジェクトの記憶域は確保時点で「erroneous value」をもつとされ、処理系がプログラムの状態に依存せず決定する何らかの値で埋められる + - 動的記憶域期間であれば不定値、静的・スレッド記憶域期間であればゼロで埋められる。C++23までは自動記憶域期間も不定値で埋められていた +- 初期化されなかったスカラ型オブジェクトなど、値表現(パディングは含まない)内のいずれかのビットに「erroneous value」をもつオブジェクトは「erroneous value」をもつとされる +- 式が評価された結果として「erroneous value」が生成された場合、「erroneous behavior」を引き起こす + - ただし、`unsigned char`(およびunsignedとなる場合は`char`)もしくは[`std::byte`](/reference/cstddef/byte.md)型の「erroneous value」がこれらの型のオブジェクトの初期化・代入に使用される場合や値が破棄される場合は「erroneous behavior」にならない + - これらのルールは、式が評価された結果として不定値が生成された場合に未定義の動作を引き起こすとする従来のルールと同様である +- 「erroneous behavior」を引き起こしたうえで生成された値は、後続の処理では「erroneous value」とはみなされない ```cpp example #include From 5e8c37d17209037ee5961fc8c96e3569c7853a3b Mon Sep 17 00:00:00 2001 From: Akira Takahashi Date: Tue, 8 Oct 2024 13:41:43 +0900 Subject: [PATCH 13/21] =?UTF-8?q?C++26=20=E6=9C=AA=E5=88=9D=E6=9C=9F?= =?UTF-8?q?=E5=8C=96=E5=A4=89=E6=95=B0=E3=81=AE=E8=AA=AD=E3=81=BF=E5=8F=96?= =?UTF-8?q?=E3=82=8A=20:=20indeterminate=E3=81=AE=E3=82=B5=E3=83=B3?= =?UTF-8?q?=E3=83=97=E3=83=AB=E3=82=B3=E3=83=BC=E3=83=89=E3=83=9F=E3=82=B9?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kazutoshi SATODA --- lang/cpp26/erroneous_behavior_for_uninitialized_reads.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md b/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md index 36e00c8832..35d2b6fe84 100644 --- a/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md +++ b/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md @@ -100,7 +100,7 @@ struct T { }; int h(T t [[indeterminate]]) { - f(t.x); // この関数呼び出しは未定義動作を引き起こす + f(t.x); // 後述の関数呼び出しはここで未定義動作を引き起こす return 0; } From afee38894e0c6f2a597c04fdb4ade49eb878ca2d Mon Sep 17 00:00:00 2001 From: Akira Takahashi Date: Tue, 8 Oct 2024 13:42:55 +0900 Subject: [PATCH 14/21] =?UTF-8?q?C++26=20=E6=9C=AA=E5=88=9D=E6=9C=9F?= =?UTF-8?q?=E5=8C=96=E5=A4=89=E6=95=B0=E3=81=AE=E8=AA=AD=E3=81=BF=E5=8F=96?= =?UTF-8?q?=E3=82=8A=20:=20=E6=8A=9C=E3=81=91=E3=81=A6=E3=81=84=E3=81=9F?= =?UTF-8?q?=E3=80=8C=E5=B8=B8=E3=81=AB=E7=9C=9F=E3=80=8D=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lang/cpp26/erroneous_behavior_for_uninitialized_reads.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md b/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md index 35d2b6fe84..35ff996457 100644 --- a/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md +++ b/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md @@ -81,8 +81,8 @@ int main() { // d2は「erroneous value」をもつ std::memcpy(&d2, &d1, sizeof(int)); - assert(e1 == d2); // 「erroneous behavior」 - assert(e2 == d2); // 「erroneous behavior」 + assert(e1 == d2); // 常に真、「erroneous behavior」 + assert(e2 == d2); // 常に真、「erroneous behavior」 } ``` From 94e04bfdf954d388d0cb96fc45b6e6ffd2c27b51 Mon Sep 17 00:00:00 2001 From: Akira Takahashi Date: Tue, 8 Oct 2024 13:45:34 +0900 Subject: [PATCH 15/21] =?UTF-8?q?C++26=20=E6=9C=AA=E5=88=9D=E6=9C=9F?= =?UTF-8?q?=E5=8C=96=E5=A4=89=E6=95=B0=E3=81=AE=E8=AA=AD=E3=81=BF=E5=8F=96?= =?UTF-8?q?=E3=82=8A=20:=20bool=E3=81=AE=E4=BE=8B=E7=A4=BA=E3=82=92?= =?UTF-8?q?=E8=A6=8B=E7=9B=B4=E3=81=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lang/cpp26/erroneous_behavior_for_uninitialized_reads.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md b/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md index 35ff996457..3e15a53f08 100644 --- a/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md +++ b/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md @@ -128,11 +128,13 @@ int main() { - 以下のようなケースでは、erroneous behaviorではなく未定義動作を引き起こす可能性がある: ```cpp T* p; // 未初期化のポインタ。erroneous value (例としてヌルポインタ) をもつ - bool b; // 未初期化の真理値。erroneous valueとして、 - // 妥当ではないbool値 (trueでもfalseでもない値) をもつ可能性がある + bool b; // 未初期化の真理値。 + // bool値として妥当な値表現をもたない可能性がある + // (例: 値表現が8bitで{0x00(false), 0x01(true)}の + // 2通りのみとする処理系で0xCCをもつなど) f(*p); // 間接参照は未定義動作を引き起こす - g(b); // bが妥当な値である場合にerroneous behavior、そうでなければ未定義動作 + g(b); // bが妥当な値表現をもつ場合にerroneous behavior、そうでなければ未定義動作 ``` From a81c832f54e04c8a0007c27565027ea6b53a24a4 Mon Sep 17 00:00:00 2001 From: Akira Takahashi Date: Thu, 10 Oct 2024 17:39:50 +0900 Subject: [PATCH 16/21] =?UTF-8?q?C++26=20=E6=9C=AA=E5=88=9D=E6=9C=9F?= =?UTF-8?q?=E5=8C=96=E5=A4=89=E6=95=B0=E3=81=AE=E8=AA=AD=E3=81=BF=E5=8F=96?= =?UTF-8?q?=E3=82=8A=20:=20=E3=80=8C=E6=98=8E=E7=A2=BA=E3=81=AB=E5=AE=9A?= =?UTF-8?q?=E7=BE=A9=E3=81=95=E3=82=8C=E3=81=9F=E5=8B=95=E4=BD=9C=E3=80=8D?= =?UTF-8?q?=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kazutoshi SATODA --- lang/cpp26/erroneous_behavior_for_uninitialized_reads.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md b/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md index 3e15a53f08..3a831694cb 100644 --- a/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md +++ b/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md @@ -24,7 +24,7 @@ int main() { 未初期化の値は、コンパイラやターゲット環境によって定義された固定値である。コンパイラにはこの誤りを診断することが許可され、推奨されているが、誤りを無視して有効な読み取りとして扱うことも許可されている。このコードは誤りではあるが、実行ごとに異なる動作をしたり攻撃者に値を制御されたりといったリスクはなくなる。 -「erroneous behavior」は未定義動作とはちがって、明確に定義された動作をするがコードとして正しくない、ということを規定するものであり、処理系に対して有用な診断を提供するものである。 +「erroneous behavior」は未定義動作(一切の保証が失われる)とはちがって、動作を定めたうえで診断も可能とするものである。 C++26では、不定値で初期化されることを明確に指示する`[[indeterminate]]`属性も導入され、以下のような動作となる: From 616c00bff8d95651754799d85cb8586476fdac14 Mon Sep 17 00:00:00 2001 From: Akira Takahashi Date: Thu, 10 Oct 2024 17:41:32 +0900 Subject: [PATCH 17/21] =?UTF-8?q?C++26=20=E6=9C=AA=E5=88=9D=E6=9C=9F?= =?UTF-8?q?=E5=8C=96=E5=A4=89=E6=95=B0=E3=81=AE=E8=AA=AD=E3=81=BF=E5=8F=96?= =?UTF-8?q?=E3=82=8A=20:=20=E4=BB=8A=E5=BE=8C=E3=81=AE=E8=A9=B1=E3=82=92?= =?UTF-8?q?=E4=BB=95=E6=A7=98=E3=81=8B=E3=82=89=E5=82=99=E8=80=83=E3=81=AB?= =?UTF-8?q?=E7=A7=BB=E5=8B=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...oneous_behavior_for_uninitialized_reads.md | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md b/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md index 3a831694cb..0681c0db68 100644 --- a/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md +++ b/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md @@ -109,6 +109,19 @@ int main() { } ``` +## 備考 +- 以下のようなケースでは、erroneous behaviorではなく未定義動作を引き起こす可能性がある: + ```cpp + T* p; // 未初期化のポインタ。erroneous value (例としてヌルポインタ) をもつ + bool b; // 未初期化の真理値。 + // bool値として妥当な値表現をもたない可能性がある + // (例: 値表現が8bitで{0x00(false), 0x01(true)}の + // 2通りのみとする処理系で0xCCをもつなど) + + f(*p); // 間接参照は未定義動作を引き起こす + g(b); // bが妥当な値表現をもつ場合にerroneous behavior、そうでなければ未定義動作 + ``` + ### 今後、「erroneous behavior」に分類される可能性のある操作 現在、未定義動作に分類される以下の操作は、「erroneous behavior」に分類できる可能性がある。 @@ -124,19 +137,5 @@ int main() { | 契約違反 | 契約に関する現在の策定作業では、契約違反時になにが起こるべきかという問題に直面している。「erroneous behavior」という概念は有用な回答を与えてくれる可能性がある | -## 備考 -- 以下のようなケースでは、erroneous behaviorではなく未定義動作を引き起こす可能性がある: - ```cpp - T* p; // 未初期化のポインタ。erroneous value (例としてヌルポインタ) をもつ - bool b; // 未初期化の真理値。 - // bool値として妥当な値表現をもたない可能性がある - // (例: 値表現が8bitで{0x00(false), 0x01(true)}の - // 2通りのみとする処理系で0xCCをもつなど) - - f(*p); // 間接参照は未定義動作を引き起こす - g(b); // bが妥当な値表現をもつ場合にerroneous behavior、そうでなければ未定義動作 - ``` - - ## 参照 - [P2795R5 Erroneous behaviour for uninitialized reads](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2795r5.html) From 82d636081ab86da01f3f55abd6593763a121e476 Mon Sep 17 00:00:00 2001 From: Akira Takahashi Date: Thu, 7 Nov 2024 14:48:15 +0900 Subject: [PATCH 18/21] =?UTF-8?q?C++26=20=E6=9C=AA=E5=88=9D=E6=9C=9F?= =?UTF-8?q?=E5=8C=96=E5=A4=89=E6=95=B0=E3=81=AE=E8=AA=AD=E3=81=BF=E5=8F=96?= =?UTF-8?q?=E3=82=8A=20:=20=E6=B1=BA=E5=AE=9A=E3=81=97=E3=81=9F=E8=A8=B3?= =?UTF-8?q?=E8=AA=9E=E3=82=92=E9=81=A9=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- GLOBAL_DEFINED_WORDS.json | 5 +- implementation-status.md | 2 +- lang/cpp26.md | 2 +- ...oneous_behavior_for_uninitialized_reads.md | 66 +++++++++---------- 4 files changed, 38 insertions(+), 37 deletions(-) diff --git a/GLOBAL_DEFINED_WORDS.json b/GLOBAL_DEFINED_WORDS.json index 8202b750d7..12ce60ba87 100644 --- a/GLOBAL_DEFINED_WORDS.json +++ b/GLOBAL_DEFINED_WORDS.json @@ -23,10 +23,11 @@ }, "未規定動作": { "redirect": "未規定の動作", "yomi": "みきていどうさ" }, "未規定": { "redirect": "未規定の動作", "yomi": "みきてい" }, - "「erroneous behavior」": { - "yomi": "えろーにあすびへいびあ", + "エラー性の動作": { + "yomi": "えらーせいのどうさ", "desc": "未定義動作ではないが、誤ったプログラムの結果とされる動作。erroneous behavior (EB)。処理系によって診断や異常終了を実行することが許可されるが、処理が続行する場合もある" }, + "エラー性動作": { "redirect": "エラー性の動作", "yomi": "えらーせいどうさ" }, "処理系定義の動作": { "link": "/implementation-compliance.md#dfn-implementation-defined-behavior", "yomi": "しょりけいていぎのどうさ", diff --git a/implementation-status.md b/implementation-status.md index 7efadc50eb..e7129063da 100644 --- a/implementation-status.md +++ b/implementation-status.md @@ -305,7 +305,7 @@ | P0609R3: [構造化束縛への属性を許可](/lang/cpp26/attributes_for_structured_bindings.md) | `auto [a, b [[maybe_unused]], c] = f();`のように構造化束縛の要素に対して属性を付加できるようにする | 15 | 19 | | | | P3034R1: [モジュール宣言でのモジュール名のマクロ展開を禁止する](/lang/cpp26/module_declarations_shouldnt_be_macros.md.nolink) | `export module MACRO_NAME;`を禁止 | | | | | | P2809R3: [自明な無限ループは未定義動作ではないと規定](/lang/cpp26/trivial_infinite_loops_are_not_undefined_behavior.md.nolink) | 並行プログラムの進行保証などを考慮して無限ループを未定義動作ではないものとする | 14 | 19 | | | -| P2795R5: [未初期化変数の読み取りを"erroneous behavior"とする](/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md) | 初期化されていない自動変数の読み取りの安全性を規定する | | | | | +| P2795R5: [未初期化変数の読み取りをエラー性動作とする](/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md) | 初期化されていない自動変数の読み取りの安全性を規定する | | | | | | P2573R2: [関数宣言を削除する理由を指定できるようにする](/lang/cpp26/delete_reason.md) | `f() = delete("reason");` | 15 | 19 | | | | P2893R3: [可変引数テンプレートで`friend`宣言をできるようにする](/lang/cpp26/variadic_friends.md.nolink) | クラステンプレートの可変引数テンプレートでまとめて`friend`宣言できるようにする | 15 | | | | | P2747R2: [`constexpr`配置`new`](/lang/cpp26/constexpr_placement_new.md.nolink) | 定数式の文脈での配置`new`を許可 | | | | | diff --git a/lang/cpp26.md b/lang/cpp26.md index fff209b541..1a2b6655ef 100644 --- a/lang/cpp26.md +++ b/lang/cpp26.md @@ -17,7 +17,7 @@ C++26とは、2026年中に改訂される予定の、C++バージョンの通 | [不完全型へのポインタに対する`delete`を不適格とする](/lang/cpp26/deleting_a_pointer_to_an_incomplete_type_should_be_ill-formed.md.nolink) | 未定義動作となる操作をコンパイルエラーとする | | [返却された左辺値から暗黙変換された一時オブジェクトが参照に束縛されることを禁止する](/lang/cpp26/disallow_binding_a_returned_glvalue_to_a_temporary.md.nolink) | 寿命切れの変数によって引き起こされるバグを防止する | | [要素数不明の配列を集成体初期化する規則を明確化](/lang/cpp26/clarifying_rules_for_brace_elision_in_aggregate_initialization.md.nolink) | 配列要素の集成体初期化で`{}`が省略された場合の矛盾していた規定を修正 | -| [未初期化変数の読み取りを「erroneous behavior」とする](/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md) | 初期化されていない自動変数の読み取りの安全性を規定する | +| [未初期化変数の読み取りをエラー性動作とする](/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md) | 初期化されていない自動変数の読み取りの安全性を規定する | ### 文字列 diff --git a/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md b/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md index 0681c0db68..17797acbc8 100644 --- a/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md +++ b/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md @@ -1,4 +1,4 @@ -# 未初期化変数の読み取りを「erroneous behavior」とする [P2795R5] +# 未初期化変数の読み取りをエラー性動作とする [P2795R5] * cpp26[meta cpp] @@ -10,7 +10,7 @@ ## 概要 -C++23までは、未初期化変数 (デフォルト初期化された変数) の読み取りは未定義動作として扱われていた。C++26では、この未定義動作による安全上のリスクを低減するため、「「erroneous behavior」 (erroneous behavior; 通称 EB)」を新設してその多くに割り当てることとした。 +C++23までは、未初期化変数 (デフォルト初期化された変数) の読み取りは未定義動作として扱われていた。C++26では、この未定義動作による安全上のリスクを低減するため、「エラー性動作 (erroneous behavior; 通称 EB、別表記としてエラー性の動作)」を新設してその多くに割り当てることとした。 ```cpp example // C++23 @@ -24,7 +24,7 @@ int main() { 未初期化の値は、コンパイラやターゲット環境によって定義された固定値である。コンパイラにはこの誤りを診断することが許可され、推奨されているが、誤りを無視して有効な読み取りとして扱うことも許可されている。このコードは誤りではあるが、実行ごとに異なる動作をしたり攻撃者に値を制御されたりといったリスクはなくなる。 -「erroneous behavior」は未定義動作(一切の保証が失われる)とはちがって、動作を定めたうえで診断も可能とするものである。 +エラー性動作は未定義動作(一切の保証が失われる)とはちがって、動作を定めたうえで診断も可能とするものである。 C++26では、不定値で初期化されることを明確に指示する`[[indeterminate]]`属性も導入され、以下のような動作となる: @@ -33,56 +33,56 @@ C++26では、不定値で初期化されることを明確に指示する`[[ind void f(int) {} int main() { - int x; // xは「erroneous value」をもつ + int x; // xはエラー性の値をもつ int y [[indeterminate]]; // 意図して不定値に初期化されることを指示 - f(x); // 「erroneous behavior」 (「erroneous value」の読み取り) + f(x); // エラー性動作 (エラー性の値の読み取り) f(y); // 未定義動作 (不定値の読み取り) } ``` ## 仕様 -- 自動記憶域期間をもつオブジェクトの記憶域は確保時点で「erroneous value」をもつとされ、処理系がプログラムの状態に依存せず決定する何らかの値で埋められる +- 自動記憶域期間をもつオブジェクトの記憶域は確保時点で「エラー性の値 (erroneous value)」をもつとされ、処理系がプログラムの状態に依存せず決定する何らかの値で埋められる - 動的記憶域期間であれば不定値、静的・スレッド記憶域期間であればゼロで埋められる。C++23までは自動記憶域期間も不定値で埋められていた -- 初期化されなかったスカラ型オブジェクトなど、値表現(パディングは含まない)内のいずれかのビットに「erroneous value」をもつオブジェクトは「erroneous value」をもつとされる -- 式が評価された結果として「erroneous value」が生成された場合、「erroneous behavior」を引き起こす - - ただし、`unsigned char`(およびunsignedとなる場合は`char`)もしくは[`std::byte`](/reference/cstddef/byte.md)型の「erroneous value」がこれらの型のオブジェクトの初期化・代入に使用される場合や値が破棄される場合は「erroneous behavior」にならない +- 初期化されなかったスカラ型オブジェクトなど、値表現(パディングは含まない)内のいずれかのビットにエラー性の値をもつオブジェクトはエラー性の値をもつとされる +- 式が評価された結果としてエラー性の値が生成された場合、エラー性動作を引き起こす + - ただし、`unsigned char`(およびunsignedとなる場合は`char`)もしくは[`std::byte`](/reference/cstddef/byte.md)型のエラー性の値がこれらの型のオブジェクトの初期化・代入に使用される場合や値が破棄される場合はエラー性動作にならない - これらのルールは、式が評価された結果として不定値が生成された場合に未定義の動作を引き起こすとする従来のルールと同様である -- 「erroneous behavior」を引き起こしたうえで生成された値は、後続の処理では「erroneous value」とはみなされない +- エラー性動作を引き起こしたうえで生成された値は、後続の処理ではエラー性の値とはみなされない ```cpp example #include int g(bool b) { unsigned char c; - unsigned char d = c; // 「erroneous behavior」ではない。dは「erroneous value」をもつ + unsigned char d = c; // エラー性動作ではない。dはエラー性の値をもつ - assert(c == d); // 常に真、「erroneous behavior」 (整数昇格) + assert(c == d); // 常に真、エラー性動作 (整数昇格) - int e = d; // 「erroneous behavior」 (型変換) - return b ? d : 0; // bがtrueの場合に「erroneous behavior」 + int e = d; // エラー性動作 (型変換) + return b ? d : 0; // bがtrueの場合にエラー性動作 } int main() { int d1, d2; - int e1 = d1; // 「erroneous behavior」 - int e2 = d1; // 「erroneous behavior」 + int e1 = d1; // エラー性動作 + int e2 = d1; // エラー性動作 // 処理が続行した場合… - assert(e1 == e2); // 常に真、「erroneous behavior」ではない。 - // 「erroneous behavior」の結果で生成された値 (e1とe2) は、 - // 「erroneous value」とはみなされない - assert(e1 == d1); // 常に真、「erroneous behavior」 - assert(e2 == d1); // 常に真、「erroneous behavior」 - - // 「erroneous behavior」ではないが - // d2は「erroneous value」をもつ + assert(e1 == e2); // 常に真、エラー性動作ではない。 + // エラー性動作の結果で生成された値 (e1とe2) は、 + // エラー性の値とはみなされない + assert(e1 == d1); // 常に真、エラー性動作 + assert(e2 == d1); // 常に真、エラー性動作 + + // エラー性動作ではないが + // d2はエラー性動作をもつ std::memcpy(&d2, &d1, sizeof(int)); - assert(e1 == d2); // 常に真、「erroneous behavior」 - assert(e2 == d2); // 常に真、「erroneous behavior」 + assert(e1 == d2); // 常に真、エラー性動作 + assert(e2 == d2); // 常に真、エラー性動作 } ``` @@ -110,21 +110,21 @@ int main() { ``` ## 備考 -- 以下のようなケースでは、erroneous behaviorではなく未定義動作を引き起こす可能性がある: +- 以下のようなケースでは、エラー性動作ではなく未定義動作を引き起こす可能性がある: ```cpp - T* p; // 未初期化のポインタ。erroneous value (例としてヌルポインタ) をもつ + T* p; // 未初期化のポインタ。エラー性の値 (例としてヌルポインタ) をもつ bool b; // 未初期化の真理値。 // bool値として妥当な値表現をもたない可能性がある // (例: 値表現が8bitで{0x00(false), 0x01(true)}の // 2通りのみとする処理系で0xCCをもつなど) f(*p); // 間接参照は未定義動作を引き起こす - g(b); // bが妥当な値表現をもつ場合にerroneous behavior、そうでなければ未定義動作 + g(b); // bが妥当な値表現をもつ場合にエラー性動作、そうでなければ未定義動作 ``` -### 今後、「erroneous behavior」に分類される可能性のある操作 +### 今後、エラー性動作に分類される可能性のある操作 -現在、未定義動作に分類される以下の操作は、「erroneous behavior」に分類できる可能性がある。 +現在、未定義動作に分類される以下の操作は、エラー性動作に分類できる可能性がある。 | 操作 | 備考 | |------|------| @@ -133,8 +133,8 @@ int main() { | 誤ったビットシフト (負のシフト幅や、上限を超えたシフト幅) | 符号付き整数のオーバーフローと同じ | | ゼロ割り | いくつかの固定値での誤った結果となる可能性がある。影響が不明確であるため、変更にはコストがかかる | | 戻り値型が非`void`な関数から返った、もしくは`[[noreturn]]`属性をつけた関数から返った | [`std::terminate()`](/reference/exception/terminate.md)が呼ばれる可能性がある。変更には軽いコストがかかるが、その変更にどの程度の価値があるかは不明 | -| 抽象クラスのコンストラクタ・デストラクタからの純粋仮想関数の呼び出し | 特定の純粋仮想ハンドラが呼ばれる可能性がある。実装によってはすでに「erroneous behavior」のように扱われている可能性がある | -| 契約違反 | 契約に関する現在の策定作業では、契約違反時になにが起こるべきかという問題に直面している。「erroneous behavior」という概念は有用な回答を与えてくれる可能性がある | +| 抽象クラスのコンストラクタ・デストラクタからの純粋仮想関数の呼び出し | 特定の純粋仮想ハンドラが呼ばれる可能性がある。実装によってはすでにエラー性動作のように扱われている可能性がある | +| 契約違反 | 契約に関する現在の策定作業では、契約違反時になにが起こるべきかという問題に直面している。エラー性動作という概念は有用な回答を与えてくれる可能性がある | ## 参照 From 6010481f4dbc9e5d44502533efe07b21c271b2a6 Mon Sep 17 00:00:00 2001 From: Koichi Murase Date: Thu, 7 Nov 2024 17:03:29 +0900 Subject: [PATCH 19/21] =?UTF-8?q?GLOBAL=5FDEFINED=5FWORDS:=20EB=20?= =?UTF-8?q?=E3=81=AB=E5=80=A3=E3=81=84=20UB=20=E3=82=82=E8=8B=B1=E5=90=8D?= =?UTF-8?q?=E3=82=92=E8=A1=A8=E8=A8=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- GLOBAL_DEFINED_WORDS.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GLOBAL_DEFINED_WORDS.json b/GLOBAL_DEFINED_WORDS.json index 12ce60ba87..a9ebb8b0ad 100644 --- a/GLOBAL_DEFINED_WORDS.json +++ b/GLOBAL_DEFINED_WORDS.json @@ -12,7 +12,7 @@ "未定義の動作": { "link": "/implementation-compliance.md#dfn-undefined-behavior", "yomi": "みていぎのどうさ", - "desc": "処理系は予期せぬ動作をする可能性がある。要するに動作保証対象外" + "desc": "処理系は予期せぬ動作をする可能性がある。要するに動作保証対象外。undefined behavior (UB)。" }, "未定義動作": { "redirect": "未定義の動作", "yomi": "みていぎどうさ" }, "未定義": { "redirect": "未定義の動作", "yomi": "みていぎ" }, From 28eb999e2472a44c289042ca3b28333d3349576e Mon Sep 17 00:00:00 2001 From: Koichi Murase Date: Thu, 7 Nov 2024 16:21:03 +0900 Subject: [PATCH 20/21] =?UTF-8?q?=E6=A8=99=E6=BA=96=E8=A6=8F=E6=A0=BC?= =?UTF-8?q?=E3=81=A8=E5=87=A6=E7=90=86=E7=B3=BB:=20=E3=82=A8=E3=83=A9?= =?UTF-8?q?=E3=83=BC=E6=80=A7=E3=81=AE=E5=8B=95=E4=BD=9C=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 --- GLOBAL_DEFINED_WORDS.json | 1 + implementation-compliance.md | 1 + 2 files changed, 2 insertions(+) diff --git a/GLOBAL_DEFINED_WORDS.json b/GLOBAL_DEFINED_WORDS.json index a9ebb8b0ad..9ce1c016ba 100644 --- a/GLOBAL_DEFINED_WORDS.json +++ b/GLOBAL_DEFINED_WORDS.json @@ -24,6 +24,7 @@ "未規定動作": { "redirect": "未規定の動作", "yomi": "みきていどうさ" }, "未規定": { "redirect": "未規定の動作", "yomi": "みきてい" }, "エラー性の動作": { + "link": "/implementation-compliance.md#dfn-erroneous-behavior", "yomi": "えらーせいのどうさ", "desc": "未定義動作ではないが、誤ったプログラムの結果とされる動作。erroneous behavior (EB)。処理系によって診断や異常終了を実行することが許可されるが、処理が続行する場合もある" }, diff --git a/implementation-compliance.md b/implementation-compliance.md index 7ba64e97dc..e2e19ed36d 100644 --- a/implementation-compliance.md +++ b/implementation-compliance.md @@ -25,6 +25,7 @@ C++ の処理系は、翻訳を担うコンパイラと実行を担うオペレ - 未規定の動作 (unspecified behavior) とされた動作に対しては、処理系は考えられる動作の内の1つを行って良い。処理系は説明書にその動作を定義しなくて良い。 - 未定義の動作 (undefined behavior; 通称 UB) は、処理系が実際に行う動作について標準規格が如何なる要件もおかないことを表す。 - **文化圏固有動作** (locale-specific behavior) に対しては、処理系は現地の国家・文化・言語の風習に依存した動作を行う。処理系はその動作を説明書に記述する必要がある。 +- エラー性の動作 (erroneous behavior; 通称 EB) は、定義された動作であるが、処理系は診断情報を出力することが推奨される。その後に未規定の時点で、処理系は実行を終了しても良い。 これらの用語は処理系が取りうる動作の範囲を示すものであって、例えば "未定義の動作" という名前の具体的な動作がある訳ではないことに注意する。 From 1c11eb89d353692111238981daf65506b80759b0 Mon Sep 17 00:00:00 2001 From: Akira Takahashi Date: Mon, 11 Nov 2024 12:57:15 +0900 Subject: [PATCH 21/21] fix typo Co-authored-by: Kazutoshi SATODA --- lang/cpp26/erroneous_behavior_for_uninitialized_reads.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md b/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md index 17797acbc8..4cf7047e09 100644 --- a/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md +++ b/lang/cpp26/erroneous_behavior_for_uninitialized_reads.md @@ -78,7 +78,7 @@ int main() { assert(e2 == d1); // 常に真、エラー性動作 // エラー性動作ではないが - // d2はエラー性動作をもつ + // d2はエラー性の値をもつ std::memcpy(&d2, &d1, sizeof(int)); assert(e1 == d2); // 常に真、エラー性動作