异步调用 class 函数时出现分段错误
Segmentation Fault when calling class functions in async
我是 c++ 的初学者,正在研究动态内存和异步函数,我不确定为什么以下代码不起作用。
我想做的是基本上动态创建一个 Loop
的对象和一个调用该对象的 start
方法的异步函数,每个分配给不同的映射变量具有相同的id 作为两者的键(示例代码中的randomthing
)。
预期:每秒打印出数字 10 到 1。
结果:分段错误
#include <iostream>
#include <vector>
#include <map>
#include <chrono>
#include <future>
class Loop{
public:
Loop(int t_):t(t_){}
void start(){
while(t>0){
std::cout << t << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
t--;
}
}
private:
int t;
};
int main()
{
std::map<std::string, std::future<void>> store;
std::map<std::string, Loop*> storeClass;
storeClass["randomthing"] = new Loop(10);
store["randomthing"] = std::async(std::launch::async, [&storeClass](){
std::cout << "starting" << std::endl;
storeClass["randomthing"]->start();
std::cout << "finished" << std::endl;
delete storeClass["randomthing"];
});
return 0;
}
我又弄乱了一点,发现这个修改有效:
将存储声明为 std::future<void> store
而不是映射,并在创建 Loop 对象后直接将异步函数分配给它。
为什么示例代码不起作用,为什么修改可以解决问题?
我正在用 -std=c++11 编译程序。
您必须确保所有变量在使用时在生命周期内有效。您的代码:
std::async(std::launch::async, [&storeClass](){
storeClass["randomthing"]->start(); // uses storeClass
});
return 0;
} // calls storeClass destructor
存在竞争条件,其中 storeClass
析构函数和 storeClass
的使用未排序。结果,当 destructor 恰好在 async 之后被调用时,那就没问题了,否则你会得到一个 seg fault。
不要使用原始指针 - 使用 std::unique_ptr
作为 Loop*
。
要解决它,您可以将 storeClass
设为 std::shared_ptr
或 unique_ptr
并 copy/move 将其放入 async
中的 lambda 运行。或者等待异步完成:
store["randomthing"] = std::async(std::launch::async, [&storeClass](){
.. use storeClass ..
});
store["randomthing"].wait(); // wait for calling `storeClass["randomthing"]
return 0;
} // will destroy storeClass
我是 c++ 的初学者,正在研究动态内存和异步函数,我不确定为什么以下代码不起作用。
我想做的是基本上动态创建一个 Loop
的对象和一个调用该对象的 start
方法的异步函数,每个分配给不同的映射变量具有相同的id 作为两者的键(示例代码中的randomthing
)。
预期:每秒打印出数字 10 到 1。
结果:分段错误
#include <iostream>
#include <vector>
#include <map>
#include <chrono>
#include <future>
class Loop{
public:
Loop(int t_):t(t_){}
void start(){
while(t>0){
std::cout << t << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
t--;
}
}
private:
int t;
};
int main()
{
std::map<std::string, std::future<void>> store;
std::map<std::string, Loop*> storeClass;
storeClass["randomthing"] = new Loop(10);
store["randomthing"] = std::async(std::launch::async, [&storeClass](){
std::cout << "starting" << std::endl;
storeClass["randomthing"]->start();
std::cout << "finished" << std::endl;
delete storeClass["randomthing"];
});
return 0;
}
我又弄乱了一点,发现这个修改有效:
将存储声明为 std::future<void> store
而不是映射,并在创建 Loop 对象后直接将异步函数分配给它。
为什么示例代码不起作用,为什么修改可以解决问题?
我正在用 -std=c++11 编译程序。
您必须确保所有变量在使用时在生命周期内有效。您的代码:
std::async(std::launch::async, [&storeClass](){
storeClass["randomthing"]->start(); // uses storeClass
});
return 0;
} // calls storeClass destructor
存在竞争条件,其中 storeClass
析构函数和 storeClass
的使用未排序。结果,当 destructor 恰好在 async 之后被调用时,那就没问题了,否则你会得到一个 seg fault。
不要使用原始指针 - 使用 std::unique_ptr
作为 Loop*
。
要解决它,您可以将 storeClass
设为 std::shared_ptr
或 unique_ptr
并 copy/move 将其放入 async
中的 lambda 运行。或者等待异步完成:
store["randomthing"] = std::async(std::launch::async, [&storeClass](){
.. use storeClass ..
});
store["randomthing"].wait(); // wait for calling `storeClass["randomthing"]
return 0;
} // will destroy storeClass