根据一篇文章(here https://alexgaynor.net/2019/apr/21/modern-c++-wont-save-us/ and there https://github.com/isocpp/CppCoreGuidelines/issues/1038)此代码是一个错误的 use-after free 示例:
#include <iostream>
#include <string>
#include <string_view>
int main() {
std::string s = "Hellooooooooooooooo ";
std::string_view sv = s + "World\n";
std::cout << sv;
}
文章中指出,string
s 将被释放时string_view
用来!这违背了我的调试经验。但我要求你确认/验证/检查这一点。
根据我的经验,堆栈/作用域变量在作用域退出时被释放(调用析构函数将是更正确的措辞)。这意味着在这种情况下,这将发生在std::cout << sv;
不过我从来没用过string_view
,所以我不知道这个对象的任何内部机制。
如果这确实是一种危险行为,你能解释一下吗?
否则,我很高兴阅读确认仅在当前作用域退出时调用作用域变量析构函数,或者在抛出异常时调用,从而中断当前作用域中的线程。
EDIT:
前两个答案之后,就真的是一个use-after-free的用法了。
附属问题:您认为我们可以在 string_view 的定义中添加一个带有 delete 关键字的移动构造函数来禁止这种情况吗?
这段代码的问题...
std::string_view sv = s + "World\n";
... 就是它sv
未设置为s
但对于一个无名的暂时的由表达式创建s + "world\n"
. That 暂时的整个表达式结束后(分号处)立即被销毁。
所以是的,这是一个“释放后使用”类型的错误。
如果你想延长它的寿命暂时的你必须将它分配给一个将维护它的变量 - 就像一个新的std::string
object:
std::string sv = s + "World\n"; // copy the temporary to new storage in sv
A std::string_view
只是字符串的“视图”,它本身不是字符串。仅当它“查看”的字符串有效时,它才有效。
这里还有另一个怪癖。您还可以绑定暂时的 to a const
参考这延长了临时的寿命:
std::string const& sv = s + "World\n"; // just keep the temporary living
为什么初始化一个std::string_view
from a 暂时的允许吗?
我不能代表标准委员会发言,但我怀疑std::string_view
预计将用作函数参数,以便可以将临时变量传递到函数中(就像使用 const ref 一样)。显然,生命周期对于这种情况来说是很好的。
如果我们禁止临时变量的初始化,那么主要使用std::string_view
会被否定。你将被迫创建一个新的std::string
(或绑定到 const ref)在调用函数之前使过程变得尴尬。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)