- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
简化概念后,严格的别名规则规定对象应该由兼容类型的指针或指向char
的指针访问。这样,编译器可以对代码进行一些假设并进行一些优化。
尽管这条规则的解释会引起一些质疑和讨论,但它本身并不是什么国家机密。所以我的问题是:
为什么一些受人尊敬的组织(由经验丰富的程序员维护)经常提交不遵守严格别名规则的代码?我可以举一个例子:在他们网站的tutorialOntcpdump
上有一个example code明显多次违反了严格的别名规则。我似乎也有很多其他代码这样做,特别是在处理网络数据包时。。
他们只是幸运的编译器没有完全破坏他们的代码,所以它没有被注意到吗?它们是否依赖于使用libpcap
标志编译的用户?考虑到一些受人尊敬的程序员,这是一种可能性——我认为Linus Torvalds自己就是一个例子,正如我在一些邮件列表中看到的那样,一个Linux代码片段可能会在启用严格别名的情况下中断——不要真的认为通过严格别名获得的优化补偿了编译器可能做出的错误假设。或者,不幸的是,这仅仅是编程社区中固有的错误代码和错误实践?
另一个问题是,来自tcpdump的-fno-strict-aliasing
代码:为什么即使使用sniffex.c
gcc -O5 -Wall -Wextra -Wstrict-aliasing=1 sniffex.c -lpcap
编译,也不会对违反的严格别名规则发出任何警告?是不是因为它在没有地址运算符时不容易检测到这些类型的punnings?
我不想再提这个话题(因为还有很多其他的问题),但即使我明白这个规则,我似乎也不明白为什么在很多地方它总是被忽视。。
编辑:
显然违反严格别名规则的示例代码片段有:
void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
{
...
/* declare pointers to packet headers */
const struct sniff_ethernet *ethernet; /* The ethernet header [1] */
const struct sniff_ip *ip; /* The IP header */
const struct sniff_tcp *tcp; /* The TCP header */
const char *payload; /* Packet payload */
...
/* define ethernet header */
ethernet = (struct sniff_ethernet*)(packet);
/* define/compute ip header offset */
ip = (struct sniff_ip*)(packet + SIZE_ETHERNET);
...
/* define/compute tcp header offset */
tcp = (struct sniff_tcp*)(packet + SIZE_ETHERNET + size_ip);
...
/* define/compute tcp payload (segment) offset */
payload = (u_char *)(packet + SIZE_ETHERNET + size_ip + size_tcp);
...
gcc 5.4.0
(原始
&
类型)的指针来访问它,因此,我认为,违反了严格的别名规则。
最佳答案
严格的别名规则是有争议的。
背景位:
注意,“严格别名规则”不是一个正式术语,但它指的是关于有效类型的第6.5/6段和关于通过指针访问数据的第6.5/7段。后一段是实际严格的混叠规则,它一直是C的一部分,只要语言已经标准化,那么它的存在实际上不会对任何人产生冲击。从ANSI-C草案到C11,6.5./7中的文本几乎完全相同。
然而,这一部分在C90中并不清楚,因为它主要关注用于“左值访问”的指针的类型,而不是实际存储在那里的数据的类型。这使得您将指针强制转换为无效指针的情况变得不清楚,例如在使用memcpy
时,或者在执行各种形式的类型双关时。
在C99中,有人试图通过引入有效类型来澄清这一点。实际上,这并没有改变严格别名规则的措辞,只是使解释变得更加清晰。(它仍然是标准中最难理解的部分之一。)
该规则的初衷是允许编译器避免奇怪的最坏情况假设,例如C99原理中的这个示例:
int a;
void f( double * b )
{
a = 1;
*b = 2.0;
g(a);
}
b
不指向
a
,这应该是一个明智的假设,因为给定了非常不同的类型,那么它可以将函数优化为
a = 1;
*b = 2.0;
g(1); // micro-optimization, doesn't have to load `a` from memory
uint32_t u32=0;
uint16_t* p16 = (uint16_t*)&u32; // grab the ms/ls word (endian-dependent)
*p16 = something;
if(u32)
do_stuff();
do_stuff()
的调用的代码,因为它可能假设代码中的任何内容都不会从值0中更改
u32
。
u32
不稳定,这样编译器就不得不读取它-这会阻止对变量的所有优化,而不仅仅是不需要的优化。或者也可以提出一种自制的联合类型,其中包含一个
uint32_t
和两个
uint16_t
。或者可能访问每个字节的u32字节。很不方便。
uint8_t
数组中,而程序员知道该数组包含一个
uint16_t
,那么我应该能够编写类似
(uint16_t*)array
的代码,而无需编译器做出“哦,看,这个数组从未使用过,让优化它走”或其他一些无意义的假设。
关于c - 严格混叠警告和tcpdump示例代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43270657/
你好,我正在尝试在 opensuse 中创建一个 Shell 脚本来创建 MySqlUsers,但是当我尝试运行它时,我得到了这个错误: Warning: Could not start progra
我阅读了有关此错误的所有信息,但未能找到任何解决方案。 我有一个看起来像这样的简单页面: $xmlfile = "/var/www/marees.xml"; //Fichier dans lequel
运行 Websphere App 服务器 V8.5 Liberty Profile。我找不到任何可以解决这些警告的帮助。我在 eclipse 。 ************** He
我尝试在 GC AppEngine 上部署应用程序。部署过程中没有错误,但应用程序无法运行(仅显示加载页面)。日志中唯一一个奇怪的原始 OpenBLAS WARNING - could not det
我刚开始学习 RestKit。我正在尝试使用它来使用 Foursquare api 获取附近的 field 。但每次我尝试“objectLoader:(RKObjectLoader *)objectL
我对 Vuejs 比较陌生,每次按键时都会收到以下警告: [Vue warn]: $attrs is readonly. found in ---> at src\component
Warning: simplexml_load_file() [function.simplexml-load-file]: I/O warning : failed to load external
我在尝试修改某些表时不断收到此错误。这是我的代码: /** = 1){ //$this->mysqli->autocommit(FALSE); //insert th
当我尝试使用 PHP 的 ftp_put 函数上传文件时,早些时候出现错误: 警告:ftp_put() [function.ftp-put]:无数据连接 现在,我尝试开启被动模式: ftp_pasv(
我一直在努力让这段代码适用于现阶段的年龄。它旨在计算一个范围内的素数,我已经编写了一种方法来打印它们。不幸的是,代码将无法编译,引用警告: “警告:[未检查] 未检查调用 add(E) 作为原始类型
尝试使用带有架构组件和Kotlin的Android Studio 3 Canary 5构建示例会给出此警告。 谁能告诉我原因? 谢谢,Ove 编辑#1: 这是Dan Lew前段时间制作的样本 http
我正在编写一个 Shiny 的应用程序,它运行得非常好,突然我收到两条警告消息。我已经回到以前运行良好的副本,它们现在显示相同的错误消息,所以我真的很困惑。我的代码仍然运行并在我 Shiny 的仪表板
03-25 05:52:15.329 8029-8042/com.mgh.radio W/MediaPlayerNative: info/warning (703, 0) 03-25 05:52:15
我在构建时在我的 gradle 控制台中收到一条警告消息: 警告:[options] 引导类路径未与 -source 1.7 一起设置 1 条警告 我怎样才能解决这个问题? 任何帮助表示赞赏! 最佳答
我有下一个代码: 测试.c #include "a1.h" int main() { int a = 8; foo(a); return a; } a1.h void foo
我的程序中有一个 WORD 变量。 WORD hour; 但是当我比较它的时候 if(hour>=0 && hour=0 && hour=0 的比较,它始终适用于 hour 是 WORD 类型,它是一
安全研究人员警告称,一个最新的严重的Java错误,其本质与目前在全球范围内利用的臭名昭著的 Log4Shell 漏洞相同 。 CVE-2021-42392 尚未在国家漏洞数据库 (NVD) 中
安装SqlServer2005时“版本变更检查 (警告)"问题排查 今天同事在安装SqlServer2005时遇到“版本变更检查 (警告) ”问题导致安装失败,警告提示如下: - 版本
我的 UWP 项目中出现以下警告。我已经标记了解决方案的示例,但我更感兴趣的是为什么在同一平台上创建另一个空项目时不会出现此警告? APPX4001: Build property AppxBundl
我试图修复我的登录脚本,在我的本地主机上它可以工作,但上传到我的在线测试服务器时,注销被破坏,我得到这个错误: Warning: session_destroy() [function.session
我是一名优秀的程序员,十分优秀!