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

c++ - 使用用户数据的严格别名和回调

我有一个带有基于回调的 C API 的 c++ 库。回调类型如下所示:

用户可以像这样注册一个回调,并可以设置一个指向任意数据的指针,库将通过回调将该指针传回。

我主要关心的是:它是否违反了严格的别名规则?我需要将 userData 的类型更改为 char* 吗?

0 投票
1 回答
868 浏览

c++ - 基于通用 char[] 的存储并避免与严格混叠相关的 UB

我正在尝试构建一个类模板,它将一堆类型打包在一个适当大的 char 数组中,并允许将数据作为单独的正确类型引用进行访问。现在,根据标准,这可能会导致违反严格别名,从而导致未定义的行为,因为我们正在char[]通过与其不兼容的对象访问数据。具体来说,标准规定:

如果程序尝试通过非下列类型之一的泛左值访问对象的存储值,则行为未定义:

  • 对象的动态类型,
  • 对象的动态类型的 cv 限定版本,
  • 与对象的动态类型类似(如 4.4 中定义)的类型,
  • 与对象的动态类型相对应的有符号或无符号类型,
  • 对应于对象动态类型的 cv 限定版本的有符号或无符号类型,
  • 聚合或联合类型,在其元素或非静态数据成员中包括上述类型之一(递归地包括子聚合或包含联合的元素或非静态数据成员),
  • 一个类型,它是对象的动态类型的(可能是 cv 限定的)基类类型,
  • 一个charunsigned char类型。

鉴于突出显示的要点的措辞,我提出了以下alias_cast想法:

(上面的测试代码,尤其是Dataclass只是一个简单的想法演示,所以请不要指出我应该如何使用std::pairor std::tuplealias_cast模板还应该扩展为处理 cv 限定类型,它只能是安全的在满足对齐要求时使用,但我希望这个片段足以证明这个想法。)

这个技巧消除了 g++ 的警告(使用 编译时g++ -std=c++11 -Wall -Wextra -O2 -fstrict-aliasing -Wstrict-aliasing),并且代码可以工作,但这真的是告诉编译器跳过基于严格别名的优化的有效方法吗?

如果它无效,那么如何在不违反别名规则的情况下实现这样的基于 char 数组的通用存储类?

编辑:用这样alias_cast的简单替换reinterpret_cast

使用 g++ 编译时会产生以下警告:

aliastest-so-1.cpp:在 'T& Data::first() 的实例化中 [with T = int; U = short unsigned int]': aliastest-so-1.cpp:28:16:
这里需要 aliastest-so-1.cpp:21:58: 警告:取消引用类型双关指针将破坏严格别名规则 [-严格锯齿]

0 投票
3 回答
3738 浏览

c++ - 释放/删除联合 malloc/C/C++ 中的新数组

我正在工作并且正在考虑使用工会。我决定反对它,因为设计确实需要一个结构/类,但它最终导致了以下假设性问题:

假设你有一个像这个人为的例子这样的联合:

. . . 然后你分配一个数组并尝试从其他地方删除它:

我认为这会起作用,尽管它在技术上没有定义,因为 malloc 的实现方式。我还假设它在分配 array_c 时会起作用,尽管与 int 与 float 不同,数组的大小不太可能相同。

可以使用类似的 new 和 delete 重复测试。我猜这些也行得通。

我猜语言规范会讨厌我这样做,但我希望它会起作用。它让我想起了“即使它是数组而不是对象,也不要删除转换为 void* 的新指针”业务。

所以问题是:规范对这样做有什么看法?我简单地检查了一下,但找不到任何特别解决这种情况的东西。无论如何,这是多么不明智——从功能的角度来看(我意识到从清晰的角度来看这很糟糕)。

这纯粹是出于迂腐目的的好奇问题。

0 投票
2 回答
2296 浏览

c++ - C ++中联合中的两个数组

是否可以像这样在联合中共享两个数组:

这两个数组共享相同的内存大小还是其中一个更长?

0 投票
2 回答
990 浏览

c++ - 联合:从联合的一个数据成员中读取以写入另一个

我知道对于下面的代码,下面的“非法”是未定义的(虽然一些编译器允许它),因为联合成员“a”是活动的,然后我们从联合成员“b”中读取。问题是,“AmILegal”中的代码是否修复了它,还是我在做一些可怕甚至更晦涩的事情?我可以使用 memcpy 来实现相同的效果,还是我在那里调用了另一个未定义的行为?

编辑:也许这个例子不够清楚。我想做的就是激活另一个成员。所以我将浮点数更改为int。虽然看起来很傻,但更接近真实案例。阅读下面的代码。

(是否出于某种原因不允许将一个工会成员复制到另一个工会成员中?)

如果以上所有内容听起来都不是很有用,请认为 a 实际上是一个与 float[4] 结合的 _m128。位表示始终是准确和正确的。在某个时间点,您将需要实际使用它,并且您需要将它作为浮点数组放在主内存中。“复制指令”实际上是从 _m128 联合成员到 float[4] 成员的 _mm_store_ps。因此,关于 memset 的问题 - 也许这是我需要的更准确的例子......

0 投票
1 回答
2824 浏览

c - 通过示例了解限制限定符

关键字的restrict行为在 C99 中由 6.7.3.1 定义:

令 D 是一个普通标识符的声明,它提供了一种将对象 P 指定为指向类型 T 的限制限定指针的方法。

如果 D 出现在一个块内并且没有存储类 extern,则让 B 表示该块。如果 D 出现在函数定义的参数声明列表中,则让 B 表示关联的块。否则,让 B 表示 main 块(或在独立环境中程序启动时调用的任何函数块)。

在下文中,如果(在对 E 求值之前执行 B 的某个序列点)修改 P 以指向它以前指向的数组对象的副本,则称指针表达式 E 基于对象 P将改变 E.119 的值)请注意,“基于”仅针对具有指针类型的表达式定义。

在每次执行 B 期间,令 L 为基于 P 具有 &L 的任何左值。如果 L 用于访问它指定的对象 X 的值,并且 X 也被修改(通过任何方式),则适用以下要求: T 不应是 const 限定的。用于访问 X 值的每个其他左值也应具有基于 P 的地址。就本子条款而言,修改 X 的每个访问也应视为修改 P。如果为 P 分配了一个指针表达式 E 的值,该指针表达式 E 基于与块 B2 关联的另一个受限指针对象 P2,则 B2 的执行应在 B 的执行之前开始,或者 B2 的执行应在任务。如果不满足这些要求,则行为未定义。

和其他人一样,我很难理解这个定义的所有复杂性。作为对这个问题的回答,对于第 4 段中的每个要求,我希望看到一组很好的示例,说明会违反要求的用法。本文:

http://web.archive.org/web/20120225055041/http://developers.sun.com/solaris/articles/cc_restrict.html

用“编译器可能假设......”的方式很好地呈现规则;扩展该模式并结合编译器可以做出的假设,以及它们如何无法保持,每个示例都会很棒。

0 投票
1 回答
120 浏览

c - 混淆调整代码以使用限制限定符

我正在尝试调整以下版本的stpcpy函数以使用restrict-qualified 指针作为其参数和内部,但我不确定简单地添加限定符是否会导致引入未定义的行为。

假设 C99 6.7.3.1 中关于访问对象的规则仅适用于访问的单个对象而不是整个数组,我认为这可能没问题,因为写入的元素只能访问一次,并且只能用于写入。但我restrict在这一点上使用起来很不舒服,不想仅仅依靠我自己的判断。

0 投票
2 回答
260 浏览

c++ - 这个联合会破坏严格的别名吗?浮点寄存器呢

我必须使用那个联合来实现一点 IEEE 技巧,这会破坏严格的混叠吗?GCC 没有发出任何警告(使用 GCC 4.5 和 4.6 进行了尝试,即使使用了迂腐的严格别名,但据我所知,GCC 并不能很好地捕捉严格的别名规则违规行为(大量误报/误报)。

那是我目前正在使用的片段,它似乎可以正常工作而没有任何警告,但某些编译器优化可能会出现副作用或未定义的行为。因此,如果那段代码在某些情况下可能不安全,我将努力将其删除。

此外,我假设这段代码需要将数据从标准寄存器移动到大多数现代 CPU 上的浮点寄存器(只是对此感到好奇),这涉及到与旧 CPU 相关的一些额外周期,对吗?

上面的代码不打算做优化,所以不要贬低我滥用优化,上面的代码是我获得某个结果的最简单方法(幸运的是,最简单的方法似乎也是最快的我的情况!),如果结果不安全,那么我将使用较慢的方法。

提前致谢

0 投票
1 回答
203 浏览

c - 关于指向 char 的通用指针和严格的别名

我不知道为什么下面的代码工作正常,没有gcc错误(-fstrict-aliasing -Wstrict-aliasing=1)。

如果我遵循严格的别名规则:

n1570, § 6.5 表达式

对象的存储值只能由具有以下类型之一的左值表达式访问:

— 与对象的有效类型兼容的类型,

— 与对象的有效类型兼容的类型的限定版本,

— 与对象的有效类型相对应的有符号或无符号类型,

— 对应于对象有效类型的限定版本的有符号或无符号类型,

— 在其成员中包含上述类型之一的聚合或联合类型(递归地,包括子聚合或包含联合的成员),或

— 一种字符类型。

*q不具有与 兼容的类型*p,要么是限定版本,要么是对应的有符号或无符号类型,要么是字符类型。

那么,为什么允许呢?

0 投票
3 回答
3630 浏览

c++ - 允许将 T* 与 char* 混淆。是否也允许反过来?

注意:此问题已被重命名并简化,以使其更具针对性和可读性。大多数评论都引用了旧文本。


根据标准,不同类型的对象可能不会共享相同的内存位置。所以这是不合法的:

然而,该标准允许这条规则有一个例外:任何对象都可以通过指向charor的指针来访问unsigned char

但是,我不清楚这是否也允许反过来。例如: