在 c++ 中使用函数装饰器(使用闭包)时出现意外的分段错误



我创建了decorator函数来向现有函数添加功能。程序输出正确的函数指针地址以及经过的时间,以按预期迭代 10 xhelloworld

然而,如果我更改decorator函数以按值(FunctionPointer original_function)获取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 << " msn";
};
}

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 更改为按值传递(使用[=])以使更改后的版本正常工作。

最新更新