问题标签 [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 投票
11 回答
249065 浏览

c++ - 什么是严格的别名规则?

当询问C 中常见的未定义行为时,人们有时会提到严格的别名规则。
他们在说什么?

0 投票
2 回答
6113 浏览

c - 对于严格的指针别名,char* 何时安全?

我一直在尝试理解严格的别名规则,因为它们适用于 char 指针。

这里说明:

始终假定 char* 可以引用任何对象的别名。

好的,所以在套接字代码的上下文中,我可以这样做:

但是有这样的声明

反之则不成立。将 char* 转换为除 char* 之外的任何类型的指针并取消引用它通常违反严格的别名规则。

这是否意味着当我接收一个 char 数组时,当我知道消息的结构时,我无法重新解释转换为结构:

由于基类型是 char 数组并且我将其转换为结构,因此第二个示例不起作用吗?在一个严格别名的世界里,你如何处理这种情况?

0 投票
2 回答
464 浏览

c - C 中的消息调度系统不会破坏严格的别名和对齐

我正在用 C 编写一个嵌入式控制系统,该系统由多个相互发送消息的任务组成(我相信这是一个相当常见的习语!),但我很难设计一种机制:

  • 很整洁
  • 是通用的
  • 是相对有效的
  • 最重要的是:独立于平台(具体来说,不违反严格混叠或对齐问题)

从概念上讲,我想将每种消息类型表示为一个单独的结构定义,并且我想要一个具有以下功能(简化)的系统:

其中 aqueue_t包含一个节点的链接列表,每个节点都有一个char buf[MAX_SIZE]字段。我所在的系统没有malloc()实现,因此需要一个全局空闲节点池,然后是以下之一(以粗体表示的感知问题):

  1. sendMsg()memcpy传入消息的一部分放入空闲节点的缓冲区中。我的理解是,除非调用者对返回值进行进一步
    处理,否则这将存在对齐问题。dequeueMsg()memcpy
  2. 或者会有一个void *getFreeBuffer()返回buf[]下一个空闲节点的函数,调用者(发送者)将把它转换为适当的指针类型。
    我的理解是,现在这将在进入的过程中出现对齐问题,并且仍然需要稍后才能避免memcpydequeueMsg()退出时出现对齐问题。
  3. 或将节点中的缓冲区重新定义queue_t为 (eg) uint32_t buf[MAX_SIZE]
    我的理解是这违反了严格的别名,并且不是独立于平台的。

我能看到的唯一其他选择是创建所有消息类型的联合以及char buf[MAX_SIZE],但我不认为这是“整洁”!

所以我的问题是,如何正确地做到这一点?

0 投票
4 回答
14539 浏览

c - 如何投射 so​​ckaddr_storage 并避免违反严格的别名规则

我正在使用 Beej's Guide to Networking 并遇到了别名问题。他提出了一个函数来返回特定结构的 IPv4 或 IPv6 地址:

这会导致 GCC 在第 3 行为sa吐出严格别名错误。据我了解,这是因为我这样调用此函数:

我猜测别名与their_addr变量的类型sockaddr_storage和另一个不同类型的指针指向同一内存的事实有关。

绕过这种坚持 , 和进入工会的最好方法sockaddr_storagesockaddr_in什么sockaddr_in6?看起来这应该是网络中的老旧领域,我只是找不到任何具有最佳实践的好例子。

另外,如果有人能准确解释混叠问题发生的位置,我将不胜感激。

0 投票
5 回答
805 浏览

c++ - 使用 (void*) 作为标识符的类型

在我的程序中,我的对象(同一个类)都必须具有唯一标识符。为了简单和性能,我选择使用对象的地址作为标识符。为了保持类型简单,我将(void*)其用作此标识符的类型。最后我有这样的代码:

这似乎工作正常,但 gcc 给了我一个严格的别名警告。我知道如果 id 用于数据传输,代码会很糟糕。幸运的是不是,但问题仍然存在:别名优化会对生成的代码产生影响吗?以及如何避免警告?

注意:我不愿意使用(char*),因为这意味着用户可以使用数据进行复制,而不能!

0 投票
2 回答
381 浏览

c - 将一种类型的值与另一种类型移动是否违反严格的别名?

使用 uint32_t 移动任何类型的项目,然后读回它们是否违反了严格的别名规则?如果是这样,它是否也违反了严格的别名规则,将 uint32_ts 数组 memcpy 到任何类型的数组,然后读回元素?

以下代码示例演示了这两种情况:

请忽略我对 32 位平台的假设。此外,如果元素的大小与 uint32_t 不同,我知道填充它们并复制正确数量的 uint32_t。我的问题集中在这样做是否违反了严格的别名。

0 投票
4 回答
1272 浏览

c++ - 试图理解 GCC 错误

我有以下代码:

当我编译如下:

我收到以下错误:

这个错误在 O3 中出现,但在 O1 中没有。我已经使用 Comeau 在线编译器 MS VC9.0 和 icc v11 编译了代码,并且在所有情况下代码编译都没有问题。

该代码与std::vector, std::deque, std::set, char*,int*迭代器一起工作正常,似乎是 std::list 实现的特定内容。

我希望有人可以对这个特定错误(警告)的含义以及如何解决它提供一些见解。

注意:GCC 版本为:

0 投票
3 回答
7990 浏览

c++ - C++ (GCC) 中的 C99 严格别名规则

据我了解,GCC 在 C++ 中支持其所有 C99 功能。但是在 C++ 代码中如何处理 C99 严格别名呢?

我知道在不相关类型之间使用 C 进行强制转换不是严格混叠安全的,并且可能会生成不正确的代码,但是 C++ 呢?由于严格别名不是 C++ 标准的一部分(对吗?),GCC 必须自己指定语义。

我在相关类型之间进行计算const_caststatic_cast转换,因此它们是安全的,同时reinterpret_cast可以打破严格的别名规则。

这是一个正确的理解吗?

0 投票
7 回答
16733 浏览

c - gcc、严格混叠和通过联合进行强制转换

你有什么恐怖故事要讲吗?GCC 手册最近添加了关于 -fstrict-aliasing 和通过联合强制转换指针的警告:

[...]获取地址,转换结果指针并取消引用结果具有未定义的行为[强调添加],即使转换使用联合类型,例如:

有没有人有一个例子来说明这种未定义的行为?

请注意,这个问题与 C99 标准所说的或没有说的无关它是关于今天gcc和其他现有编译器的实际功能。

我只是猜测,但一个潜在的问题可能在于设置d为 3.0。因为d它是一个永远不会直接读取的临时变量,也永远不会通过“有点兼容”的指针读取,所以编译器可能不会费心去设置它。然后 f() 将从堆栈中返回一些垃圾。

我简单、天真的尝试失败了。例如:

工作正常,给予CYGWIN:

查看汇编程序,我们看到gcc完全优化t了: f1()简单地存储预先计算的答案:

whilef2()将 3333333.0 推入浮点堆栈,然后提取返回值:

并且这些函数也是内联的(这似乎是一些微妙的严格混叠错误的原因),但这与这里无关。(而且这个汇编器没有那么重要,但它增加了确凿的细节。)

另请注意,获取地址显然是错误的(或正确的,如果您试图说明未定义的行为)。例如,正如我们知道这是错误的:

我们同样知道这是错误的:

有关这方面的背景讨论,请参见例如:

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1422.pdf
http://gcc.gnu.org/ml/gcc/2010-01/msg00013.html
http:// davmac.wordpress.com/2010/02/26/c99-revisited/
http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html(=
在 Google 上搜索页面然后查看缓存页面)

什么是严格的别名规则?
C++ (GCC) 中的 C99 严格别名规则

在第一个链接中,七个月前 ISO 会议的会议记录草稿,一位参与者在第 4.16 节中指出:

有没有人认为规则足够清晰?没有人能够真正解释它们。

其他说明:我的测试是使用 gcc 4.3.4,使用 -O2;选项 -O2 和 -O3 暗示 -fstrict-aliasing。GCC 手册中的示例假定 sizeof(double) >= sizeof(int); 他们是否不平等并不重要。

此外,正如 Mike Acton 在 cellperformace 链接中所指出的,这里的示例生成了-Wstrict-aliasing=2,但不是。 =3warning: dereferencing type-punned pointer might break strict-aliasing rules

0 投票
6 回答
32468 浏览

c - gcc、严格混叠和恐怖故事

gcc-strict-aliasing-and-casting-through-a-union 中,我询问是否有人遇到过通过指针进行联合双关的问题。到目前为止,答案似乎是否定的。

这个问题更广泛:你有任何关于 gcc 和严格混叠的恐怖故事吗?

背景:引用AndreyT 在 c99-strict-aliasing-rules-in-c-gcc 中的回答

“严格的别名规则植根于自 [标准化] 时代开始以来存在于 C 和 C++ 中的部分标准。禁止通过另一种类型的左值访问一种类型的对象的条款存在于 C89/90 (6.3 ) 以及在 C++98 (3.10/15) 中......只是并非所有编译器都想要(或敢于)强制执行或依赖它。”

好吧,gcc现在敢于这样做了,它的-fstrict-aliasingswitch。这引起了一些问题。例如,参见关于 Mysql 错误的优秀文章 http://davmac.wordpress.com/2009/10/ ,以及http://cellperformance.beyond3d.com/articles/2006/06/understanding中同样出色的讨论-strict-aliasing.html

其他一些不太相关的链接:

再说一遍,你有自己的恐怖故事吗?当然,指出的问题将是首选。-Wstrict-aliasing也欢迎其他 C 编译器。

6 月 2 日添加: Michael Burr 的回答中的第一个链接,确实符合恐怖故事的条件,可能有点过时(从 2003 年开始)。我做了一个快速测试,但问题显然已经消失了。

资源:

具体投诉如下:

一些用户抱怨说,当 [above] 代码在没有 -fno-strict-aliasing 的情况下编译时,write 和 memcpy 的顺序是相反的(这意味着一个虚假的 len 被 mem 复制到流中)。

编译代码,在 CYGWIN 上使用gcc 4.3.4 和 -O3 (如果我错了,请纠正我——我的汇编器有点生疏了!):

对于迈克尔回答中的第二个链接,

gcc通常(总是?)会发出警告。但我相信一个有效的解决方案(对于gcc)是使用:

我已经问过这在gcc-strict-aliasing-and-casting-through-a-union中是否可行,但到目前为止没有人不同意。