我对C ++ lambdas和变量捕获(通过引用)有点问题。一个lambda捕获变量以更改其值,而另一个lambda捕获它以读取值。一切都在同一个线程上运行。
bool isRunning = true; // variable to be captured
Cedar::Input input;
input.registerOnQuit([&]()->void {
isRunning = false; // wrong address, value is constrained to lambda
});
Cedar::Platform platform;
platform.run([&](double t, double dt)->bool {
input.pump(); // internally fires the handler passed to registerOnQuit()
return isRunning; // correct address
});
如果有任何帮助,在内部使用void
指针将lambdas装入C回调中。但是,我怀疑这就是问题所在,因为从本质上讲,两个lambdas正在经历完全相同的过程而一个是有效的,而另一个则没有。
// boxes the broken lambda
using OnQuit = std::function<void()>;
void registerOnQuit(OnQuit event) {
Cedar_Input_registerOnQuitC([](void *data)->void {
(*(OnQuit *)data)();
}, (void *)&event);
}
// boxes the working lambda
using Hook = std::function<bool(double, double)>;
void run(Hook hook) {
Cedar_Platform_runC([](double t, double dt, void *data)->bool {
return (*(Hook *)data)(t, dt);
}, (void *)&hook);
}
解
我提供了Cedar::Input
和Cedar::Platform
类字段来存储lambda的副本。
// fix to Cedar::Platform::run() is similar
using OnQuit = std::function<void()>;
void registerOnQuit(OnQuit event) {
m_onQuit = event;
Cedar_Input_registerOnQuitC([](void *data)->void {
(*(OnQuit *)data)();
}, (void *)&m_onQuit);
}
答案 0 :(得分:1)
您正在存储悬空指针:
void registerOnQuit(OnQuit event) {
Cedar_Input_registerOnQuitC([](void *data)->void {
(*(OnQuit *)data)();
}, (void *)&event); // <-- saving a pointer to event here
// <-- event goes out of scope here
}
这是未定义的行为。你在其他情况下做同样的事情,它恰好在那里工作。