C ++ 20での後の実行時の決定に基づいて、異なる暗黙のオブジェクトが存在する可能性はありますか?


11

この質問は、最新のC ++ 20ドラフトへのP0593の追加に言及しています。

これが私の例です:

#include <cstdlib>
#include <cstdio>

void foo(void *p)
{
    if ( std::getchar() == 'i' )
    {
        *(int *)p = 2;
        std::printf("%d\n", *(int *)p);
    }
    else
    {
        *(float *)p = 2;
        std::printf("%f\n", *(float *)p);
    }
}

int main()
{
    void *a = std::malloc( sizeof(int) + sizeof(float) );
    if ( !a ) return EXIT_FAILURE;

    foo(a);
    // foo(a);    [2]
}

このコードは、最新のドラフトのすべての入力に対して明確に定義されていますか?

P0593で表現されている根拠により[2]、2つのユーザー入力項目が異なる場合、コメントを解除すると厳密なエイリアス違反により未定義の動作が発生することがかなり明確になります。暗黙的なオブジェクトの作成は、の時点で一度だけ行われることになっていmallocます。の割り当てステートメントではトリガーされませんfoo

プログラムの実際の実行では、プログラムを明確に定義する暗黙のオブジェクトの未指定のセットのメンバーが存在します。しかし、[intro.object] / 10で言及されている暗黙のオブジェクト作成を選択する必要があるかどうかは、私には明らかではありませんmalloc。または、決定が「タイムトラベル」できるかどうか。

バイナリblobをバッファーに読み込んで、それへのアクセス方法を実行時に決定するプログラム(たとえば、逆シリアル化、およびヘッダーがfloatまたはintが起動するかどうかを通知するプログラム)でも同じ問題が発生する可能性があります。

回答:


9

暗黙的なオブジェクトの作成は、の時点で一度だけ行われることになっていmallocます。の割り当てステートメントではトリガーされませんfoo

それは関係ありません。重要なのは、どのオブジェクトが作成されるかです。標準では、作成されるオブジェクトは、UBであったものを明確に定義されたコードにするものであると述べています。

その操作により、プログラムの動作が定義された場合に、指定されたストレージ領域で暗黙的ライフタイムタイプ([basic.types])のゼロ個以上のオブジェクトのライフタイムが暗黙的に作成および開始されます。

動作は最終的には静的分析ではなく、実行時の実行に基づいています。したがって、動作が定義されない場合でも、問題の操作時にあるタイプのオブジェクトがそのストレージに作成された場合に定義される場合まで、プログラムの実行に従う必要があります。

したがって、作成場所は常に「操作」ですが、作成されるものの決定は、実行時のメモリの使用方法(つまり、動作)に基づいています。


2
明確に言うと、私のコードは明確に定義されているということですか?
MM

2
@MM:その通りです。
Nicol Bolas
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.