问题标签 [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.
c++ - 什么是严格的别名规则?
当询问C 中常见的未定义行为时,人们有时会提到严格的别名规则。
他们在说什么?
c - 对于严格的指针别名,char* 何时安全?
我一直在尝试理解严格的别名规则,因为它们适用于 char 指针。
这里说明:
始终假定 char* 可以引用任何对象的别名。
好的,所以在套接字代码的上下文中,我可以这样做:
但是有这样的声明
反之则不成立。将 char* 转换为除 char* 之外的任何类型的指针并取消引用它通常违反严格的别名规则。
这是否意味着当我接收一个 char 数组时,当我知道消息的结构时,我无法重新解释转换为结构:
由于基类型是 char 数组并且我将其转换为结构,因此第二个示例不起作用吗?在一个严格别名的世界里,你如何处理这种情况?
c - C 中的消息调度系统不会破坏严格的别名和对齐
我正在用 C 编写一个嵌入式控制系统,该系统由多个相互发送消息的任务组成(我相信这是一个相当常见的习语!),但我很难设计一种机制:
- 很整洁
- 是通用的
- 是相对有效的
- 最重要的是:独立于平台(具体来说,不违反严格混叠或对齐问题)
从概念上讲,我想将每种消息类型表示为一个单独的结构定义,并且我想要一个具有以下功能(简化)的系统:
其中 aqueue_t
包含一个节点的链接列表,每个节点都有一个char buf[MAX_SIZE]
字段。我所在的系统没有malloc()
实现,因此需要一个全局空闲节点池,然后是以下之一(以粗体表示的感知问题):
sendMsg()
将memcpy
传入消息的一部分放入空闲节点的缓冲区中。我的理解是,除非调用者对返回值进行进一步
处理,否则这将存在对齐问题。dequeueMsg()
memcpy
- 或者会有一个
void *getFreeBuffer()
返回buf[]
下一个空闲节点的函数,调用者(发送者)将把它转换为适当的指针类型。
我的理解是,现在这将在进入的过程中出现对齐问题,并且仍然需要稍后才能避免memcpy
在dequeueMsg()
退出时出现对齐问题。 - 或将节点中的缓冲区重新定义
queue_t
为 (eg)uint32_t buf[MAX_SIZE]
。
我的理解是这违反了严格的别名,并且不是独立于平台的。
我能看到的唯一其他选择是创建所有消息类型的联合以及char buf[MAX_SIZE]
,但我不认为这是“整洁”!
所以我的问题是,如何正确地做到这一点?
c - 如何投射 sockaddr_storage 并避免违反严格的别名规则
我正在使用 Beej's Guide to Networking 并遇到了别名问题。他提出了一个函数来返回特定结构的 IPv4 或 IPv6 地址:
这会导致 GCC 在第 3 行为sa吐出严格别名错误。据我了解,这是因为我这样调用此函数:
我猜测别名与their_addr
变量的类型sockaddr_storage
和另一个不同类型的指针指向同一内存的事实有关。
绕过这种坚持 , 和进入工会的最好方法sockaddr_storage
是sockaddr_in
什么sockaddr_in6
?看起来这应该是网络中的老旧领域,我只是找不到任何具有最佳实践的好例子。
另外,如果有人能准确解释混叠问题发生的位置,我将不胜感激。
c++ - 使用 (void*) 作为标识符的类型
在我的程序中,我的对象(同一个类)都必须具有唯一标识符。为了简单和性能,我选择使用对象的地址作为标识符。为了保持类型简单,我将(void*)
其用作此标识符的类型。最后我有这样的代码:
这似乎工作正常,但 gcc 给了我一个严格的别名警告。我知道如果 id 用于数据传输,代码会很糟糕。幸运的是不是,但问题仍然存在:别名优化会对生成的代码产生影响吗?以及如何避免警告?
注意:我不愿意使用(char*)
,因为这意味着用户可以使用数据进行复制,而不能!
c - 将一种类型的值与另一种类型移动是否违反严格的别名?
使用 uint32_t 移动任何类型的项目,然后读回它们是否违反了严格的别名规则?如果是这样,它是否也违反了严格的别名规则,将 uint32_ts 数组 memcpy 到任何类型的数组,然后读回元素?
以下代码示例演示了这两种情况:
请忽略我对 32 位平台的假设。此外,如果元素的大小与 uint32_t 不同,我知道填充它们并复制正确数量的 uint32_t。我的问题集中在这样做是否违反了严格的别名。
c++ - 试图理解 GCC 错误
我有以下代码:
当我编译如下:
我收到以下错误:
这个错误在 O3 中出现,但在 O1 中没有。我已经使用 Comeau 在线编译器 MS VC9.0 和 icc v11 编译了代码,并且在所有情况下代码编译都没有问题。
该代码与std::vector
, std::deque
, std::set
, char*
,int*
迭代器一起工作正常,似乎是 std::list 实现的特定内容。
我希望有人可以对这个特定错误(警告)的含义以及如何解决它提供一些见解。
注意:GCC 版本为:
c++ - C++ (GCC) 中的 C99 严格别名规则
据我了解,GCC 在 C++ 中支持其所有 C99 功能。但是在 C++ 代码中如何处理 C99 严格别名呢?
我知道在不相关类型之间使用 C 进行强制转换不是严格混叠安全的,并且可能会生成不正确的代码,但是 C++ 呢?由于严格别名不是 C++ 标准的一部分(对吗?),GCC 必须自己指定语义。
我在相关类型之间进行计算const_cast
和static_cast
转换,因此它们是安全的,同时reinterpret_cast
可以打破严格的别名规则。
这是一个正确的理解吗?
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
,但不是。 =3
warning: dereferencing type-punned pointer might break strict-aliasing rules
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-aliasing
switch。这引起了一些问题。例如,参见关于 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中是否可行,但到目前为止没有人不同意。