c++ - 在 C++ 中使用函数装饰器(使用闭包)时出现意外的分段错误
问题描述
我创建了decorator
函数来为现有函数添加功能。helloworld
程序输出正确的函数指针地址以及按预期迭代 10 x 所经过的时间。
然而,如果我将decorator
函数更改为original_function
取值 ( FunctionPointer original_function
),程序会以分段错误终止,我不知道它失败的原因。
#include <iostream>
#include <chrono>
typedef void (*FunctionPointer)();
auto
decorator(FunctionPointer && original_function) // if changed to FunctionPointer original_function, it causes segmentation fault when the closure(lambda expression) is called later on
{
std::cout << "Decorator: " << (void*)original_function << std::endl; // 0x558072fb0b90
return [&]()
{
std::cout << "Decorator: " << (void*)original_function << std::endl; // 0x558072fb0b90 but 0x0 when original_function passed by value
auto t0 = std::chrono::high_resolution_clock::now();
original_function();
auto duration = std::chrono::high_resolution_clock::now() - t0;
std::cout << "\nElapsed " << duration.count() * 1000.0f << " ms\n";
};
}
void
helloworld(void)
{
for (auto i = 0; i < 10; i++)
std::cout << "Hello, World!\n";
}
int
main(void)
{
std::cout << "Main: " << (void*)helloworld << std::endl; // 0x558072fb0b90
auto my_helloworld = decorator(helloworld);
my_helloworld();
return 0;
}
解决方案
不同的是,当你通过值传递函数时,传入 lambda 的参数是对函数参数的引用,返回时超出范围decorator
。当您稍后调用返回的 lambda 时,您会引用这个超出范围的变量,即未定义的行为。
它在您通过通用引用传递时起作用,传递给的参数decorator
是一个引用,它被传递给 lambda。所以以后调用 lambda 时它仍然有效。
您可以将 lambda 更改为按值传递(使用[=]
)以使更改后的版本正常工作。
推荐阅读
- python - 如何使用 Windows 批处理文件运行 R 脚本,然后运行 Python 脚本,然后运行 T-SQL 查询?
- concurrency - 将循环分成线程的最佳方法?
- sql-server - 数据总是从以前的数据库中获取,而不是从新的数据库中获取
- c# - Unity如何仅使用坐标允许对象在某个边界内移动
- python - Python多进程无法腌制opencv videocapture对象
- spring-boot - 为什么 SBA JMX Bean 管理报告错误?
- python - 在不同的行上打印每个参数
- javascript - CSS过渡下拉菜单,应该很简单
- python - 删除一系列标题中的字符串
- android - 隐藏 Android Navigator 显示边框