后期破坏功能参数 [英] Late destruction of function parameters

查看:121
本文介绍了后期破坏功能参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

According to 5.2.2/4 "Function call" in n4640 (8.2.2/4 in n4659) function parameters are created and destroyed in the context of the caller. And implementations are allowed to delay the destruction of function parameters to the end of the enclosing full expression (as an implementation-defined feature). Note that the choice is not unspecified, but rather implementation-defined.

(尚不清楚这与3.3.3块范围"(n4659中的6.3.3)如何一致,这似乎暗示函数参数具有块范围,然后是3.7.3自动存储".持续时间"(n4659中的6.7.3),它表示块作用域变量的存储将一直持续到创建它们的块退出为止.但是,让我们假设我在措词中遗漏/误解了.显然现在函数参数将具有它们自己的范围)

(It is not entirely clear how this agrees with 3.3.3 "Block scope" (6.3.3 in n4659), which seems to imply that function parameters have block scope, and then 3.7.3 "Automatic storage duration" (6.7.3 in n4659), which says that the storage for block scope variables lasts until the block in which they are created exits. But let's assume that I'm missing/misunderstanding something in the wording. Apparently now function parameters will have their own scope)

据我所知,ABI要求GCC和Clang将对功能参数的破坏延迟到完整表达式的末尾,即这是这些编译器的实现定义的行为.我猜想在这样的实现中,只要将引用/指针返回到函数参数中就可以了,只要这些引用/指针仅在调用表达式中使用即可.

As far as I know, ABI requires GCC and Clang to delay the destruction of function parameters to the end of full expression, i.e. this is the implementation-defined behavior of these compilers. I would guess that in implementations like that it should be OK to return references/pointers to function parameters as long as these references/pointers are used within the calling expression only.

但是,以下示例在GCC中存在段错误,在Clang中可以正常工作

However, the following example segfaults in GCC and works fine in 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的引用,该参数存活的时间足够长以产生预期的输出.

Both compilers issue a warning about returning a reference to a local variable, which is perfectly appropriate here. A quick inspection of the generated code shows that both compilers do indeed delay the destruction of the parameter to the end of the expression. However, GCC still deliberately returns a "null reference" from foo, which causes the crash. Meanwhile, Clang behaves "as expected", returning a reference to its parameter s, which survives long enough to produce the expected output.

(在这种情况下,GCC很容易被愚弄

(GCC is easy to fool in this case by simply doing

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

它修复了GCC下的段错误.

which fixes the segfault under GCC.)

在这种情况下,在保证参数过时"销毁的前提下,GCC的行为是否合理?我是否遗漏了标准中的其他段落,即即使通过实现延长了其寿命,对返回的函数参数的引用也始终是未定义的?

Is GCC's behavior justified in this case, under assumption that it guarantees "late" destruction of parameters? Am I missing some other passage in the standard that says that returning references to function parameters is always undefined, even if their lifetimes are extended by the implementation?

推荐答案

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

As far as I know, ABI requires GCC and Clang to delay the destruction of function parameters to the end of full expression

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

The question relies heavily on this assumption. Let's see if it's correct. Itanium C++ ABI draft 3.1.1 Value Parameters says

如果该类型具有非平凡的析构函数,则在将全表达式括起来之后,调用者将在控制权返回给它之后(包括调用者抛出异常时)调用该析构函数.

If the type has a non-trivial destructor, the caller calls that destructor after control returns to it (including when the caller throws an exception), at the end of enclosing full-expression.

ABI并未定义 lifetime ,因此让我们检查C ++标准草案N4659 [basic.life]

The ABI doesn't define lifetime, so let us check C++ standard draft N4659 [basic.life]

1.2 ...类型T的对象o的生存期在以下情况下结束:

1.2 ... The lifetime of an object o of type T ends when:

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

1.3 if T is a class type with a non-trivial destructor (15.4), the destructor call starts, or ...

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

1.4 the storage which the object occupies is released, or is reused by an object that is not nested within o ([intro.object]).

C ++标准规定,在这种情况下,当调用析构函数时,生存期结束.因此,ABI确实要求函数参数的生存期延长函数调用的完整表达.

The C++ standard says that lifetime ends in this case when the destructor is called. As such, the ABI does indeed require that the lifetime of a function parameter extends the full expression of the function call.

假设实现定义了要求,那么我在示例程序中看不到UB,因此它在保证遵循Itanium C ++ ABI的任何实现上都应具有预期的行为. GCC似乎违反了该规定.

Assuming that implementation defined requirement, I see no UB in the example program, so it should have expected behaviour on any implementation that guarantees to follow the Itanium C++ ABI. GCC appears to violate that.

GCC文档声明

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

From GCC version 3 onwards the GNU C++ compiler uses an industry-standard C++ ABI, the Itanium C++ ABI.

因此,已证明的行为可被视为错误.

As such, the demonstrated behaviour could be considered a bug.

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

On the other hand, it is unclear whether this consequence of the changed wording of [expr.call] is intentional. The consequence might be considered to be a defect.

...,这表示块作用域变量的存储将持续到创建它们的块退出为止.

... which says that the storage for block scope variables lasts until the block in which they are created exits.

的确.但是您引用的 [expr.call] /4表示"函数参数是在呼叫者的上下文中创建的并销毁的.这样,存储将持续到函数调用的块结束为止.似乎与存储时间没有冲突.

Indeed. But the [expr.call]/4 that you quoted says "function parameters are created and destroyed in the context of the caller". As such, the storage lasts until the end of the block of the function call. There appears to be no conflict with the storage duration.

请注意,C ++标准链接指向的站点是根据 current 草稿定期生成的,因此可能与我引用的N4659不同.

Note that the C++ standard links point to a site that is periodically generated from the current draft and therefore may differ from N4659 that I've quoted.

这篇关于后期破坏功能参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆