相关疑难解决方法(0)

什么是严格别名规则?

当询问C中常见的未定义行为时,灵魂比我提到的严格别名规则更加开明.
他们在说什么?

c strict-aliasing undefined-behavior type-punning

778
推荐指数
10
解决办法
19万
查看次数

在C++ 11(或更高版本)中从字节数组反序列化对象的无定义行为方式是什么?

为了克服对齐问题,我需要记忆成一个临时的.临时的那种类型是什么?gcc抱怨以下reinterpret_cast将破坏严格的别名规则:

template <typename T>
T deserialize(char *ptr) {
    static_assert(std::is_trivially_copyable<T>::value, "must be trivially copyable");
    alignas(T) char raw[sizeof(T)];
    memcpy(raw, ptr, sizeof(T));
    return *reinterpret_cast<T *>(raw);
}
Run Code Online (Sandbox Code Playgroud)

(例如,当T为"长"时).

我不想定义T,因为我不想在覆盖之前构造T.

在一个联合中,不写一个成员然后读另一个计数作为未定义的行为?

template<typename T>
T deserialize(char *ptr) {
    union {
        char arr[sizeof(T)];
        T obj;
    } u;

    memcpy(u.arr, ptr, sizeof(T));   // Write to u.arr
    return u.obj;   // Read from u.obj, even though arr is the active member.
}
Run Code Online (Sandbox Code Playgroud)

c++ strict-aliasing c++11

11
推荐指数
1
解决办法
335
查看次数

std :: launder和严格别名规则

考虑以下代码:

void f(char * ptr)
{
    auto int_ptr = reinterpret_cast<int*>(ptr); // <---- line of interest 
    // use int_ptr ... 
}

void example_1()
{
    int i = 10;    
    f(reinterpret_cast<char*>(&i));
}

void example_2()
{
    alignas(alignof(int)) char storage[sizeof(int)];
    new (&storage) int;
    f(storage);
}
Run Code Online (Sandbox Code Playgroud)

感兴趣的行与example_1的调用:

Q1:在调用端,char指针使整数指针别名化.这是有效的.但是将它强制转换为int也是有效的吗?我们知道int在其生命周期内,但考虑该函数是在另一个转换单元中定义的(未启用链接时优化)并且上下文未知.然后所有编译器看到的是:int指针想要为char指针设置别名,这违反了严格的别名规则.允许这样吗?

Q2:考虑到不允许.我们在C++ 17中得到了std :: launder.它的一种指针优化屏障主要用于访问一个对象,该对象将新的位置放入其他类型的对象的存储中或者当涉及const成员时.我们可以用它来给编译器一个提示并防止未定义的行为吗?

从example_2调用的兴趣行:

Q3:这里应该要求std :: launder,因为这是Q2中描述的std :: launder用例,对吧?

auto int_ptr = std::launder(reinterpret_cast<int*>(ptr));
Run Code Online (Sandbox Code Playgroud)

但是再次考虑f在另一个翻译单元中定义.编译器如何知道我们的新位置,这发生在呼叫端?编译器(仅查看函数f)如何区分example_1和example_2?或者仅仅是低调的,因为严格的别名规则只会排除所有内容(记住char*to int*不允许)并且编译器可以做他想做的事情?

跟进问题:

Q4:如果由于别名规则导致上述所有代码都出错,请考虑更改函数f以获取void指针:

void f(void* ptr)
{
    auto int_ptr = reinterpret_cast<int*>(ptr); 
    // use …
Run Code Online (Sandbox Code Playgroud)

c++ strict-aliasing placement-new language-lawyer c++17

7
推荐指数
1
解决办法
536
查看次数