- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我们看到两个都有悬挂引用的例子:示例 A:
int& getref()
{
int a;
return a;
}
示例 B:
int& getref()
{
int a;
int&b = a;
return b;
}
我们用相同的主要功能来调用它们:
int main()
{
cout << getref() << '\n';
cout << "- reached end" << std::endl;
return 0;
}
在示例 A 中,我在读取悬空引用时收到编译器警告和预期的段错误。在示例 B 中,我既没有收到警告也没有收到段错误,而是意外地返回了正确的 a 值。
为什么B没有警告?
目前已在 2 台机器上测试。
这不是关于什么是悬空引用的问题,而是关于警告和扩展编译器行为的问题!这是未定义的行为。是的,程序理论上可以做任何事情,甚至可以引爆世界或实际工作。“这是未定义的行为”不是一个令人满意的答案,因为它只回答程序能够做什么,而不回答为什么编译器在示例 B 中甚至没有检测到这一点。
因此这不是 this question 的重复项.
程序在示例 B 中似乎没有可重现的运行时错误,也没有警告,这一事实可能只是巧合,也可能不是巧合。
我冒昧地使用了 Compiler Explorer查看生成的代码在 g++ 7.5 下,特别是 getref()
在汇编中的作用。示例 A:
getref():
push rbp
mov rbp, rsp
mov eax, 0
pop rbp
ret
示例 B:
getref():
push rbp
mov rbp, rsp
lea rax, [rbp-12]
mov QWORD PTR [rbp-8], rax
mov rax, QWORD PTR [rbp-8]
pop rbp
ret
现在我的程序集有点生疏了,但在示例 B 中似乎涉及更多的堆栈内存,从理论上讲,这会产生更多的内存被悬空引用的可能性,因此更容易被检测到,因为它不太可能被进行优化。令我感到惊讶的是,编译器在仅处理寄存器时检测到悬挂引用,但在涉及实际内存时却检测不到,例如在示例 B 的汇编中。
也许这里的任何人都知道为什么 B 比 A 更难检测。
以下是示例 B 的完整程序集,以备感兴趣:
getref():
push rbp
mov rbp, rsp
lea rax, [rbp-12]
mov QWORD PTR [rbp-8], rax
mov rax, QWORD PTR [rbp-8]
pop rbp
ret
.LC0:
.string "- reached end"
main:
push rbp
mov rbp, rsp
call getref()
mov eax, DWORD PTR [rax]
mov esi, eax
mov edi, OFFSET FLAT:_ZSt4cout
call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
mov esi, 10
mov rdi, rax
call std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char)
mov esi, OFFSET FLAT:.LC0
mov edi, OFFSET FLAT:_ZSt4cout
call std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)
mov esi, OFFSET FLAT:_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
mov rdi, rax
call std::basic_ostream<char, std::char_traits<char> >::operator<<(std::basic_ostream<char, std::char_traits<char> >& (*)(std::basic_ostream<char, std::char_traits<char> >&))
mov eax, 0
pop rbp
ret
__static_initialization_and_destruction_0(int, int):
push rbp
mov rbp, rsp
sub rsp, 16
mov DWORD PTR [rbp-4], edi
mov DWORD PTR [rbp-8], esi
cmp DWORD PTR [rbp-4], 1
jne .L7
cmp DWORD PTR [rbp-8], 65535
jne .L7
mov edi, OFFSET FLAT:_ZStL8__ioinit
call std::ios_base::Init::Init() [complete object constructor]
mov edx, OFFSET FLAT:__dso_handle
mov esi, OFFSET FLAT:_ZStL8__ioinit
mov edi, OFFSET FLAT:_ZNSt8ios_base4InitD1Ev
call __cxa_atexit
.L7:
nop
leave
ret
_GLOBAL__sub_I_getref():
push rbp
mov rbp, rsp
mov esi, 65535
mov edi, 1
call __static_initialization_and_destruction_0(int, int)
pop rbp
ret
最佳答案
B ... returns the correct value of a unexpectedly.
由于程序的行为是未定义的,所以任何行为都不应是意外的。
此外,无论返回什么值,都没有任何“正确”的地方。简直就是垃圾。
I am surprised by the compiler detecting the dangling reference whilst only ...
编译器几乎不可能检测到所有通过无效引用的间接访问。因此,一定存在编译器检测不到的复杂点。您已经在该比喻性“点”的不同侧面找到了两个示例。目前还不清楚为什么这会让您感到惊讶。
Maybe anyone here as any insight as to why B is harder to detect than A.
它更复杂。返回的引用不是直接从本地对象初始化的,而是从理论上可以引用非本地对象的另一个引用初始化的。直到分析该中间引用的初始化程序,我们才会发现它确实引用了一个本地对象。
所以,C++ 的观点被“It's UB”彻底回答了。也许您可能想知道为什么生成的汇编程序表现不同。
mov eax, 0
这仅仅是因为案例 A 生成的程序返回内存值 0,即 null。地址 0 处的内存当然不会映射为您的进程可以访问的内容,因此当程序尝试读取该内存时,操作系统会发出 SEGFAULT 信号。
mov rax, QWORD PTR [rbp-8]
另一方面,B 程序返回一个指向堆栈的指针。由于该地址已映射到进程,因此操作系统没有理由发出信号。
就其值(value)而言,GCC 确实会检测到错误并在启用优化后为不同的函数生成相同的程序集。
关于c++ - g++ 带有悬空引用的不完整警告行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64849568/
具体详细介绍请看下文: 在使用文件进行交互数据的应用来说,使用FTP服务器是一个很好的选择。本文使用Apache Jakarta Commons Net(commons-net-3.3.jar)
我在日志文件中收到这些警告: WARN 2013-01-15 00:08:15,550 org.eclipse.jetty.http.HttpParser- HttpParser Full for
我在使用特定网页时遇到问题。当我按下链接时,我收到应用程序错误(不是 http 错误等,而是应用程序级别错误)。 但是我打开了开发人员工具和网络控制台,我看到没有请求发送到服务器。 所以我双击并选择查
我没有组装经验,但这是我一直在做的。如果在通过程序集中的指针传递参数和调用函数时缺少任何基本方面,我希望输入。 例如,我想知道是否应该还原ecx,edx,esi,edi,。我读到它们是通用寄存器,但我
我没有组装经验,但这是我一直在做的。如果在通过程序集中的指针传递参数和调用函数时缺少任何基本方面,我希望输入。 例如,我想知道是否应该还原ecx,edx,esi,edi,。我读到它们是通用寄存器,但我
我正在尝试创建完整 uiscrollview 的快照,所有内容大小,我已经搜索了很多,并且我在 SO 上找到了一些东西,如下所示: Getting a screenshot of a UIScroll
我想复制一个包含以下结构的Vector,对我来说重要的是在修改复制的 vector 时保持原始Vector完整: public class objet_poid_n { public int
给定一个示例字符串 s = '嗨,我的名字是 Humpty-Dumpty,来自“爱丽丝,爱丽丝镜中奇遇记”',我想将其分成以下 block : # To Do: something like {l =
已关闭。此问题旨在寻求有关书籍、工具、软件库等的建议。不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以
我正在尝试创建一个正则表达式来查找文本中的 Linux 文件路径,但是正则表达式对我来说非常陌生。我有下面的代码片段,它将识别下面文件结构的开头。 .*(/bin/|/home/).* 完成正则表达式
我正在寻找远程托管的 JPG 的尺寸、宽度和高度。我已经了解了如何通过下载完整图像来执行此操作。 但是,如果我可以通过仅下载足以获取此信息的方式来做到这一点,那将是理想的。 典型的图像大小为 200K
有没有办法让下面的代码: import traceback def log(message): print "%s: %s" %(traceback.extract_stack()[0:-1]
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 3 年前。 Improve this qu
git show 显示了修订版中所做的所有更改。但是,它会打印出所有更改——而不仅仅是文件名。 git show --stat 只显示文件名,但它把它们截断了!有没有办法获得已更改文件名的完整列表?
Closed. This question does not meet Stack Overflow guidelines。它当前不接受答案。 想要改善这个问题吗?更新问题,以便将其作为on-topi
当我在模板中调用我的模型 get_absolute_url 方法时,我想要一个绝对/完整的 url。在我的入门模型中,我有以下内容: def get_absolute_url(self): r
我正在使用 jQuery 1.5.1 这是我的代码: $('.cellcontent').animate({ left: '-=190'}, { easing: alert('start
我正在使用下面的方法删除条形图并使用新数据更新条形图,但这样做时出现了一个小故障/完整的图表消失 1 秒,直到加载新数据。但是是否可以通过仅增加/减少柱形而不实际消失图表来实现相同的目的。 d3.se
基于 this question 中的讨论,任何人都可以提供代码或代码链接,显示 NumericLiteralX 模块的完整实现(例如 this one )?我对 NumericLiteralX 模块
我的目标是检索网站的 html,并将其转换为可读的String。我下面的代码可以工作,但我遇到了一个技术问题:当我尝试检索 http://time.gov/HTML5 的 html 时,我在 andr
我是一名优秀的程序员,十分优秀!