问题标签 [strict-aliasing]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
8 回答
9291 浏览

c++ - 将 float 类型转换为 int 的正确方法是什么,反之亦然?

下面的代码通过一些位黑客来执行快速的平方根逆运算。该算法可能是由 Silicon Graphics 在 1990 年代早期开发的,它也出现在 Quake 3 中。 更多信息

但是,我从 GCC C++ 编译器收到以下警告:取消引用类型双关指针将破坏严格别名规则

我应该使用static_cast,reinterpret_cast还是dynamic_cast在这种情况下使用?

0 投票
1 回答
516 浏览

c - Berkley Sockets,打破了别名规则?

我问我自己,我可以使用具有严格别名的 BSD 套接字,而不会通过使用 gcc 编译得到未定义的行为吗?

据我所知,这行代码打破了严格的别名规则(并且 gcc 给了我同样的警告)。那么是否有一个计划 b,在 O3 模式下使用套接字而不进行严格混叠?当然,在不违反规则的情况下?还是我必须运行一个可以在所有系统/编译器上运行的自己的套接字系统?

0 投票
2 回答
274 浏览

c - 最好的未定义行为,是边界突破吗?- 错误的指针算术?或者只是 -ignore 的别名?

我现在用 c99 工作了几个星期,专注于未定义的行为。我想在遵守规则的同时测试一些奇怪的代码。结果是这段代码:

(请原谅我的变量名,我吃了一个小丑)

所以这段代码是最好的未定义行为。我得到不同的结果,无论我没有访问任何我不拥有的内存区域,也没有访问任何未初始化的内存。(AFAIK)

第一个关键规则是,我不允许添加或减去指针,这会让它们离开数组边界。但是我可以将指针转换为整数,我可以根据需要进行计算,不是吗?

我的第二个假设是因为我被允许为指针分配一个有效的地址,将这个计算的地址分配给一个指针是一个有效的操作。由于我使用的是 char 指针,因此也不会违反严格的别名规则,因为 char* 可以对任何东西进行别名。

那么哪条规则被打破了,这会导致 UB?

单个变量也可以理解为“数组”,我违反了这个规则吗?

— 指向或超出数组对象和整数类型的指针的加法或减法会产生不指向或仅超出同一数组对象的结果(6.5.6)。

如果是这样,我也可以这样做吗?

因为结果几乎可以肯定是未定义的行为。使用 MSVC2010 编译它会输出预期的“U”,但在使用 clang 和 gcc 的 freeBSD 上,我每次都会根据优化级别得到非常有趣和不同的结果。(在我看来,行为定义不应该如此)。

那么有什么想法是导致这种鼻龙的原因吗?

0 投票
1 回答
290 浏览

c++ - 从成员函数指针转换为另一种类型并返回严格别名问题?

我写了一个类来存储一个函数指针或一个成员函数指针(不能同时存储两者)。当我存储成员函数指针时,我也存储了一个对象指针(接收器)。

问题是:我事先不知道对象的类型和函数签名,所以我使用模板类型名。对于参数,我使用可变参数模板。

我有一个类似的代码:

由于只需要一个全局函数或成员函数,因此我将所有内容都放在union.

在构造函数中,我将成员函数mem转换为 avoid (Undefined::*)(Args...)并存储它。我从 std::function 的实现中获得了这个技巧。

使用没有捕获的 lambda,我再次转换为原始类型,对象和函数,我称之为:

我将此 lambda 存储在call函数指针中以在内部调用它operator()。使用 if-else 语句比较类型数据,然后调用正确的指针。

我知道这有点烦人,但它确实有效。我有很多测试,都通过了。但我担心严格的混叠问题。我做了很多指针转换,我不确定这是否属于未定义的行为。

问题:是否允许从Ret (Object::*)(Args...)to 转换void (UndefinedClass::*)(Args...)?(RetObjectArgs是模板参数)注意我从来没有在没有再次转换为原始类型的情况下调用对象。它仅用于存储。

问题::我必须用 编译-fno-strict-aliasing吗?如果我必须,而且这是一个模板类,我应该-fno-strict-aliasing在每个项目中使用这个类吗?char也许我可以使用一个长度数组sizeof(void (UndefinedClass::*)(Args...))或类似的东西。

笔记:

  1. 我在 Archlinux 中使用 gcc 4.8.1。我使用 C++11。
  2. 我没有在这里使用 std::function 只是为了将占位符与 std::bind 一起使用(我不知道所需的占位符的数量)。毕竟这是一个很好的实践和学习。如果您知道如何使用 std::function 执行此操作,非常欢迎回答。
  3. 实际上,我在 std::vector 中使用这个类来调用相同签名的许多“回调”(信号/插槽类框架)。

太感谢了。如果需要,我会澄清这个混乱的任何方面:)

0 投票
1 回答
227 浏览

c++ - FFTW:如何防止破坏别名规则?

我有一个使用该std::complex<double>类型的代码。来自FFTW 手册

如果你有一个变量complex<double> *x,你可以通过它直接传递给 FFTW reinterpret_cast<fftw_complex*>(x)

但是,当我在我的代码中执行此操作时:

我明白了dereferencing type-punned pointer might break strict-aliasing rules [-Wstrict-aliasing]。如何解决这个警告?谢谢 !

0 投票
3 回答
280 浏览

c - 通过 void 修改任何数据指针是否合法**

通过 a 访问指针类型是否合法void **

我查看了关于指针别名的标准引用,但我仍然不确定这是否是合法的 C:

微不足道的例子,但它适用于我所看到的更复杂的情况。

似乎这不合法,因为我int *通过类型不是int *or的变量访问char *。对此我无法得出一个简单的结论。

有关的:

0 投票
3 回答
2556 浏览

c++ - C++ 中的共享内存缓冲区不违反严格的别名规则

我在不违反 C99 严格的别名规则的情况下努力实现共享内存缓冲区。

假设我有一些代码可以处理一些数据并且需要一些“临时”内存来操作。我可以这样写:

然后我有另一个函数可以做一些其他的事情,也需要一个暂存缓冲区:

问题是 foo() 和 bar() 在操作过程中可能会被多次调用,并且在整个地方进行堆分配可能在性能和内存碎片方面非常糟糕。一个明显的解决方案是分配一个适当大小的公共共享内存缓冲区,然后将其作为参数传递给 foo() 和 bar(),BYOB 样式:


我想我现在有两个问题:
- 如何实现不违反别名规则的共享公共暂存内存缓冲区?
- 尽管上面的代码确实违反了严格的别名规则,但别名并没有“伤害”。因此,任何理智的编译器都可以生成(优化的)代码,但仍然会给我带来麻烦吗?

谢谢

0 投票
4 回答
672 浏览

c++ - C/C++ 严格别名、对象生命周期和现代编译器

我对 C++ 严格别名规则及其可能的影响感到困惑。考虑以下代码:

查看 C++ 规范,第 3.10.10 节,从技术上讲,给定的代码似乎都没有违反那里给出的“别名规则”:

如果程序试图通过以下类型之一以外的左值访问对象的存储值,则行为未定义:
... 合格访问器类型列表 ...

  • *f = 1.0f;不会违反规则,因为无法访问存储的值,即我只是通过指针写入内存。我不是从记忆中读取或试图在这里解释一个值。
  • 该行int32_t b = a;不违反规则,因为我是通过其原始类型访问的。
  • float g = *f;出于同样的原因,这条线并没有违反规则。

另一个线程中,成员 CortAmmon 实际上在响应中提出了相同的观点,并补充说,通过写入活动对象产生的任何可能的未定义行为,如 中 *f = 1.0f;,将由标准的“对象生命周期”定义(似乎是对于 POD 类型来说微不足道)。

但是:互联网上有大量证据表明上述代码将在现代编译器上产生 UB。例如,请参见此处此处
大多数情况下的论点是编译器可以自由考虑&a并且f不会相互混淆,因此可以自由地重新调度指令。

现在最大的问题是,这种编译器行为是否实际上是对标准的“过度解释”。
该标准唯一一次专门讨论“别名”是在 3.10.10 的脚注中,其中清楚地表明这些是管理别名的规则。
正如我之前提到的,我没有看到任何上述代码违反标准,但很多人(可能还有编译器人员)会认为它是非法的。

我真的很感激这里的一些澄清。

小更新:
正如成员 BenVoigt 正确指出的那样,在某些平台上int32_t可能无法对齐,float因此给定的代码可能违反了“存储足够对齐和大小”的规则。我想说的int32_t是,在大多数平台上故意选择与此一致,float并且此问题的假设是类型确实对齐。

小更新#2:
正如几位成员所指出的,这条线int32_t b = a;可能违反了标准,尽管不是绝对肯定的。我同意这一观点,并且不改变问题的任何方面,请读者从我上面的声明中排除该行,即没有任何代码违反标准。

0 投票
0 回答
261 浏览

c++ - C++:通过联合绕过严格别名,然后使用 __restrict 扩展

我想知道是否可以为专门设计的情况定制严格的别名要求,同时仍然保留一般的严格别名或分别进行 -O2/-O3 优化。

更准确地说,在需要的情况下,可以使用匿名联合绕过严格的别名(如此处和此处所指出的

现在我想知道在__restrict通过这种强制转换获得的指针上使用是否会在编译器中重新启用无别名优化(或者如果这样的指针及其所有副本一直被认为是潜在的别名)。像这样:

0 投票
1 回答
1618 浏览

c - 如何在未对齐的缓冲区中使用结构

在我的网络应用程序中,在接收到的缓冲区中,我想使用偏移量作为指向已知结构的指针。使用 memcpy() 复制结构的每个字段 2 次 (rx/tx) 很繁重。我知道我在 cortex-a8 上的 gcc 4.7.2(选项:-O3)在 1 条指令中执行 memcpy(&a,&buff,4) 未对齐。因此,他可以访问未对齐的 int。假设它可能有很多结构或大结构。最好的方法是什么?