是否使用new char []或malloc的结果强制转换为float *是否为UB(严格违反别名)? [英] Is using the result of new char[] or malloc to casted float * is UB (strict aliasing violation)?

查看:113
本文介绍了是否使用new char []或malloc的结果强制转换为float *是否为UB(严格违反别名)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

其中哪些代码具有UB(具体来说,这违反了严格的别名规则)?

Which code of these has UB (specifically, which violates strict aliasing rule)?

void a() {
    std::vector<char> v(sizeof(float));
    float *f = reinterpret_cast<float *>(v.data());
    *f = 42;
}

void b() {
    char *a = new char[sizeof(float)];
    float *f = reinterpret_cast<float *>(a);
    *f = 42;
}

void c() {
    char *a = new char[sizeof(float)];
    float *f = new(a) float;
    *f = 42;
}

void d() {
    char *a = (char*)malloc(sizeof(float));
    float *f = reinterpret_cast<float *>(a);
    *f = 42;
}

void e() {
    char *a = (char*)operator new(sizeof(float));
    float *f = reinterpret_cast<float *>(a);
    *f = 42;
}

我之所以这样问,是因为存在这个问题.

I ask this, because of this question.

我认为,d没有UB(否则malloc在C ++中将毫无用处).因此,bc& e也没有.我在某处错了吗?也许b是UB,但c不是?

I think, that d doesn't have UB (or else malloc would be useless in C++). And because of this, it seems logical, that b, c & e doesn't have it either. Am I wrong somewhere? Maybe b is UB, but c is not?

推荐答案

序言:存储对象是C ++中的不同概念. 存储是指内存空间,对象是具有生命周期的实体,可以在一块存储中创建和销毁.随着时间的推移,存储可能会被重新用于托管多个对象.所有对象都需要存储,但是可以有没有对象的存储.

Preamble: storage and objects are different concepts in C++. Storage refers to memory space, and objects are entities with lifetimes, that may be created and destroyed within a piece of storage. Storage may be re-used for hosting multiple objects over time. All objects require storage, but there can be storage with no objects in it.

c 是正确的.即使该存储中已有对象,新放置"也是在存储中创建对象的有效方法之一(C ++ 14 [intro.object]/1).重复使用存储可隐式销毁旧对象,只要它们没有非平凡的析构函数([basic.life]/4),这是完全可以的. new(a) float;创建类型为float的对象,并在现有存储中创建动态存储持续时间([expr.new]/1).

c is correct. Placement-new is one of the valid methods of creating an object in storage (C++14 [intro.object]/1), even if there were pre-existing objects in that storage. The old objects are implicitly destroyed by the re-use of the storage, and this is perfectly fine so long as they did not have non-trivial destructors ([basic.life]/4). new(a) float; creates an object of type float and dynamic storage duration within the existing storage ([expr.new]/1).

d e 未被遗漏定义:仅当该表达式引用一个对象时,才定义通过glvalue表达式访问内存的效果;而不是当表达式引用不包含任何对象的存储时. (注意:关于现有定义的明显不足,请不要留下非建设性的意见.)

d and e are undefined by omission in the current object model rules: the effect of accessing memory via a glvalue expression is only defined when that expression refers to an object; and not for when the expression refers to storage containing no objects. (Note: please do not leave non-constructive comments regarding the obvious inadequacy of the existing definitions).

这并不意味着"malloc是无用的"; mallocoperator new的作用是获得存储.然后,您可以在存储中创建对象并使用这些对象.实际上,这正是标准分配器和new表达式的工作方式.

This does not mean "malloc is useless"; the effect of malloc and operator new is to obtain storage. Then you can create objects in the storage and use those objects. This is in fact exactly how standard allocators, and the new expression, work.

a b 是严格的别名冲突:类型为float的glvalue用于访问类型不兼容的对象char. ([basic.lval]/10)

a and b are strict aliasing violations: a glvalue of type float is used to access objects of incompatible type char. ([basic.lval]/10)

有建议这将使所有情况都得到明确定义(下面提到的 a 的对齐方式除外):在此建议下,使用*f隐式在位置中创建该类型的对象,但有一些注意事项

There is a proposal which would make all of the cases well-defined (other than the alignment of a mentioned below): under this proposal, using *f implicitly creates an object of that type in the location, with some caveats.

注意:在 b e 的情况下,没有对齐问题,因为保证了new-expression和::operator new可以为任何类型正确分配对齐的存储( [new.delete.single]/1).

Note: There is no alignment problem in cases b through e, because the new-expression and ::operator new are guaranteed to allocate storage correctly aligned for any type ([new.delete.single]/1).

但是,在std::vector<char>的情况下,即使标准指定调用::operator new来获取存储,该标准也不要求将第一个矢量元素放置在该存储的第一个字节中.例如向量可以决定在前面分配3个额外的字节,并将其用于簿记.

However, in the case of std::vector<char>, even though the standard specifies that ::operator new be called to obtain storage, the standard doesn't require that the first vector element be placed in the first byte of that storage; e.g. the vector could decide to allocate 3 extra bytes on the front and use those for some book-keeping.

这篇关于是否使用new char []或malloc的结果强制转换为float *是否为UB(严格违反别名)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆