繁体   English   中英

功能参数的延迟破坏

[英]Late destruction of function parameters

根据n4640中的5.2.2 / 4“函数调用”(n4659中的8.2.2 / 4 ),在调用者的上下文中创建和销毁函数参数。 并且允许实现将函数参数的破坏延迟到封闭的完整表达式的末尾(作为实现定义的特征)。 请注意,选择不是未指定的 ,而是实现定义的

目前还不完全清楚这与3.3.3“块范围”(n4659中的6.3.3)是否一致,这似乎意味着函数参数具有块范围,然后是3.7.3“自动存储持续时间”(6.7.3)在n4659)中,它表示块作用域变量的存储一直存在,直到它们被创建的块退出。但是我们假设我在措辞中缺少/误解了某些东西。 显然现在函数参数将有自己的范围

据我所知,ABI要求GCC和Clang将函数参数的销毁延迟到完全表达式的末尾,即这是这些编译器的实现定义行为。 我猜想在类似的实现中,只要在调用表达式中使用这些引用/指针,就可以返回对函数参数的引用/指针。

但是,以下示例在GCC中的段错误并且在Clang中正常工作

#include <iostream>
#include <string>

std::string &foo(std::string s)
{
  return s;
}

int main()
{
   std::cout << foo("Hello World!") << std::endl;
}

两个编译器都发出关于返回对局部变量的引用的警告,这在这里是完全合适的。 快速检查生成的代码表明,两个编译器确实将参数的破坏延迟到表达式的末尾。 但是,GCC仍然故意从foo返回一个“空引用”,这会导致崩溃。 同时,Clang表现为“按预期”,返回对其参数s的引用,该参数存活足够长以产生预期输出。

(简单来说,GCC在这种情况下很容易愚弄

std::string &foo(std::string s)
{
  std::string *p = &s;
  return *p;
}

它修复了GCC下的段错误。)

在这种情况下GCC的行为是否合理,假设它保证参数的“晚期”破坏? 我是否遗漏了标准中的其他段落,即返回对函数参数的引用始终未定义,即使它们的生命周期是由实现扩展的?

据我所知,ABI要求GCC和Clang将函数参数的破坏延迟到完整表达式的末尾

这个问题在很大程度上依赖于这个假设。 让我们看看它是否正确。 Itanium C ++ ABI草案3.1.1值参数

如果类型具有非平凡的析构函数,则在封闭full-expression结束时,调用者在控制返回之后调用该析构函数(包括调用者抛出异常时)。

ABI没有定义生命周期 ,所以让我们检查一下C ++标准草案N4659 [basic.life]

1.2 ...类型T的对象o的生命周期结束时:

1.3如果T是具有非平凡析构函数(15.4)的类类型,则析构函数调用开始,或者......

1.4对象占用的存储被释放,或被未嵌套在o中的对象重用([intro.object])。

C ++标准表示,在调用析构函数时,生命周期结束。 因此,ABI确实要求函数参数的生命周期扩展函数调用的完整表达式。

假设实现定义了需求,我在示例程序中看不到UB,因此它应该在任何保证遵循Itanium C ++ ABI的实现上具有预期的行为。 海湾合作委员会似乎违反了这一点。

GCC文档确实说明了这一点

从GCC版本3开始,GNU C ++编译器使用行业标准的C ++ ABI,即Itanium C ++ ABI。

因此,证明的行为可能被视为一个错误。

另一方面,不清楚[expr.call]改变措辞的后果是否是故意的。 结果可能被认为是一个缺陷。


...表示块作用域变量的存储一直持续到创建它们的块为止。

确实。 但是你引用的[expr.call] / 4表示“函数参数是 调用者上下文创建和销毁 因此,存储一直持续到函数调用块的结尾。 似乎与存储持续时间没有冲突。


请注意,C ++标准链接指向从当前草稿定期生成的站点,因此可能与我引用的N4659不同。

从5.2.2 / 4函数调用[expr.call],在我看来GCC是正确的:

参数的生命周期在定义它的函数返回时结束。 每个参数的初始化和销毁​​发生在调用函数的上下文中。

好吧,我从前C ++ 14标准中给出以下答案,阅读C ++ 17,我认为GCC和Clang都是正确的:

来自:N4659 8.2.2 / 4函数调用[expr.call]

实现定义参数的生命周期是在定义它的函数返回时还是在封闭的完整表达式的末尾结束。 每个参数的初始化和销毁​​发生在调用函数的上下文中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM