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

c - 访问长双位表示

TLDR;以下代码是否调用未定义(或未指定)的行为?

在我的 x86-64 机器上,输出取决于传递给编译器的特定优化标志(gcc-4.8.0、-O0 与 -O1)。

使用-O0,我得到

使用-O1时,我得到

请注意倒数第二行中的额外 1。此外,在 memset 之后取消注释打印指令会使 1 消失。这似乎依赖于两个事实:

  1. long double 被填充,即 sizeof(long double) = 16 但只使用了 10 个字节。
  2. 对 memset 的调用可能会被优化掉
  3. long doubles 的填充位可能会在没有通知的情况下发生变化,即 value1 和 value2 上的浮点运算似乎会扰乱填充位。

我正在编译-std=c99 -Wall -Wextra -Wpedantic并且没有收到任何警告,所以我不确定这是一个严格的混叠违规情况(但很可能是)。通过-fno-strict-aliasing并没有改变任何事情。

上下文是在此处描述的 HDF5 库中发现的错误。HDF5 在计算浮点类型的本机位表示方面做了一些调整,但如果填充位不保持为零,它就会感到困惑。

所以:

  1. 这是未定义的行为吗?
  2. 这是一个严格的混叠违规吗?

谢谢。

编辑:这是 printme 的代码。我承认我只是从某个地方剪切和粘贴而没有过多关注它。如果问题出在这儿,我会脱下裤子绕过桌子。

0 投票
2 回答
2029 浏览

c - 如何将 dlsym() 的返回值分配给函数类型?

我的问题如下:

我有一个包含这样的函数指针的结构:

现在我想为它分配一个正是该类型的函数指针。但可悲dlsym()的是返回 avoid *而不是类似的东西function_poitner_type

所以我的第一次尝试:

以警告结束:

警告:ISO C 禁止函数指针和 'void *' 之间的赋值

好吧,这让我很困惑...... gcc 从来没有对我说得那么严厉。但是好吧,让我们变得棘手,我认为可能会有任何后门来保持它符合标准。所以我尝试了这个:

嗯……显然……

警告:取消引用类型双关指针将破坏严格的别名规则

因为我不知道dlsym()内部会发生什么,所以我不知道我会崩溃,因为我返回了一个为void *我的函数起别名的实数,或者完全不同的东西,可以吗?

所以我不知道,现在使用这个函数指针会破坏严格的别名规则还是不会?

但无论如何:对于我的公司来说,使用 compilerflag 是合法的-fstrict-aliasing。所以这对我来说也不是一个可能的解决方案,即使它符合要求。

所以我继续尝试。

我的下一个想法是:将一个char *版本解析dlsym()成 memcopy 怎么样?

结果:

我现在收到的警告再次非常具体:

警告:ISO C 禁止在函数指针和 'void *' 之间传递 'memcpy' 的参数 1

所以我的下一个想法是“让我们回到字节”也许我会找到一种方法。(但慢慢地我的想法已经用完了......)

所以我做了:

这以一个安静的不同警告结束:

警告:ISO C 禁止将函数指针转换为对象指针类型

所以最后我最奇怪的尝试是:

甚至这里的问题是,它offsetoff的第二个参数不能被转换为,void *因为它是一个函数指针。

我被卡住了,不知道如何走得更远,有人可以帮我找到解决方案吗?

我只是使用gcc 4.2而不是clang来得到这些警告。

目标 C 版本是-std=c99为了避免 is-std=POSIX-std=gnu99

但是这个 gcc 警告对我来说听起来并不过时。我目前正在使用 FreeBSD,我真的不知道如何解决这个问题。

0 投票
2 回答
13124 浏览

c - 将缓冲区解释为结构的正确、可移植的方式

我的问题的背景是网络编程。假设我想通过网络在两个程序之间发送消息。为简单起见,假设消息看起来像这样,字节顺序不是问题。我想找到一种正确、可移植且有效的方法来将这些消息定义为 C 结构。我知道有四种方法:显式强制转换、通过联合强制转换、复制和编组。

显式铸造:

我的理解是这send_message不违反别名规则,因为字节/字符指针可以别名任何类型。但是,反之亦然,因此receive_message违反了别名规则,因此具有未定义的行为。

通过联合铸造:

然而,这似乎违反了工会在任何给定时间只包含其成员之一的想法。此外,如果源缓冲区未在字/半字边界上对齐,这似乎会导致对齐问题。

复制:

这似乎可以保证产生正确的结果,但我当然更愿意不必复制数据。

编组

仍然必须复制,但现在与结构的表示分离。但是现在我们需要明确每个成员的位置和大小,字节序是一个更明显的问题。

相关资料:

什么是严格的别名规则?

在不违反标准的情况下使用指向结构的指针对数组进行别名

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

http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html

现实世界的例子

我一直在寻找网络代码的示例,以了解如何在其他地方处理这种情况。轻量级的ip也有几个类似的案例。udp.c文件中包含以下代码:

其中struct udp_hdr是 udp 标头的打包表示,p->payload类型为void *. 根据我的理解和这个答案,这绝对是[edit-not] 破坏严格混叠,因此具有未定义的行为。

0 投票
1 回答
798 浏览

c++ - 使用aligned_storage 时如何避免严格的混叠错误

std::aligned_storage用作变体模板的后备存储。问题是,一旦我-O2在 gcc 上启用,我开始收到“取消引用类型双关指针将破坏严格别名”的警告。

真正的模板要复杂得多(在运行时检查类型),但生成警告的最小示例是:

我很确定boost::variant正在做与此基本相同的事情,但我似乎无法找到他们如何避免这个问题。

我的问题是:

  • 如果aligned_storage以这种方式使用违反了严格混叠,我应该如何使用它?
  • get()鉴于函数中没有其他基于指针的操作, 实际上是否存在严格混叠问题?
    • 如果get()是内联呢?
    • 怎么样get() = 4; get() = 3.2int由于类型不同,该序列是否可以重新排序float
0 投票
2 回答
2213 浏览

c++ - MSVC++ 限制关键字和局部变量

我已经阅读了许多关于restrict关键字的帖子。但几乎我能找到的每个示例似乎都只将输入参数引用到一个函数,也许是一个值。我需要澄清我的理解。

我发现一个函数看起来完全违反了带有输入参数和局部变量的关键字规则。

这个函数被调用void*到一个缓冲区并且指针被声明为__restrict(这是Microsoft Visual C++)。然而,在函数的后面,UCHAR*声明了一个类型的局部变量指针,并使其指向相同的受限输入参数缓冲区。

这是我正在谈论的功能的一个严重削减的版本:

上面的例子是否违反了规则restrict

0 投票
1 回答
249 浏览

c - `restrict` 关键字隐含的严格别名级别是多少?

我有以下结构:

并像这样使用它:

我的问题是:删除严格别名是否d也会影响其成员,还是我需要restrict单独使用它们?换句话说,是否restrict暗示结构中包含的所有指针都得到相同的处理?

编辑:通过别名级别,我的意思是,如果一个指向结构的指针被restrict编辑,那么包含在其中的任何其他指针也会受到限制(就像我的例子一样)。

0 投票
2 回答
117 浏览

c++ - 允许将 (double *) 转换为 (double **) 吗?

因为我遵循了一个讨论,其中被告知“通过不兼容的指针类型进行别名是未定义的行为”(例如double d; int *p = (int *)&d;以下问题:

是否允许强制(double *)转换为(double **),例如double *d1; double **d2 = &d2 d2[0][y]使用类似于期望的语法d1[y]

我知道它不是通过不兼容的指针类型完全别名,但是我不确定。背景是我想要一个对二维数组(=图像)进行操作的函数,但我希望能够只传递图像的行或列。

0 投票
3 回答
4963 浏览

c++ - 为什么优化会杀死这个功能?

我们最近在大学举办了一场关于多种语言编程专题的讲座。

讲师写下了以下函数:

虽然我完全理解这在可读性方面也是非常糟糕的风格,但他的主要观点是这部分代码在生产代码中运行良好,直到它们启用了高优化级别。然后,代码什么也不做。

他说所有对变量的赋值tmp都会被编译器优化掉。但是为什么会这样呢?

我知道在某些情况下需要将变量声明为volatile以便编译器不会触及它们,即使他认为它们从未被读取或写入,但我不知道为什么会发生这种情况。

0 投票
2 回答
813 浏览

c++ - 不使用放置 new 返回的指针时的 C++ 严格别名

这可能会导致未定义的行为吗?


char具有严格混叠的特殊规则。如果我使用char而不是 uint8_t它仍然是未定义的行为吗?还有什么变化?

正如成员 DeadMG 指出的那样,reinterpret_cast依赖于实现。如果我改用 C 风格的演员(int32_t*)storage表,会发生什么变化?

0 投票
3 回答
296 浏览

c++ - 将“this”指针转换为另一种类型不会违反严格的别名?

所以如果我做这样的事情:

注意:“m_data”和“this”应该指向同一个地方...

GCC 4.8.1