如何从C++ POCO Task获取返回数据?私有std::vector数据丢失问题
问题:POCO Task执行后成员变量数据失效
我在使用C++ POCO库的Task类时遇到一个问题——runTask()执行完毕后,动态分配的内存变量似乎被释放了。比如示例里的私有成员_series,在runTask()完成后会变成空,导致getSeries()无法返回有效数据。
#include <Poco/Task.h> #include <Poco/TaskManager.h> #include <iostream> #include <vector> class FibonacciTask: public Poco::Task { public: FibonacciTask(int n): Task("FibonacciTask"), _n(n) {} void runTask() { long long a = 0, b = 1; _series.push_back(a); _series.push_back(b); for (int i = 2; i <= _n; i++) { long long temp = a + b; a = b; b = temp; _series.push_back(b); if (isCancelled()) { std::cout << "\nTask cancelled." << std::endl; break; } } } const std::vector<long long>& getSeries() const { return _series; } private: int _n; std::vector<long long> _series; };
我尝试用私有std::vector变量加getter方法访问,但无法正常工作,以下是运行异常的输出:
> g++ -I/usr/local/include/Poco -o prog main.cpp -L/usr/local/lib -lPocoFoundation > ./prog 0 1 1 2 3 5 8 13 21 34 55 0 139993720817872 1 2 3 5 8 13 21 34 55 0 139993720817872 1 2 3 5 8 13 21 34 55
测试用的完整代码:
#include <Poco/Task.h> #include <Poco/TaskManager.h> #include <iostream> #include <vector> #include <unistd.h> class FibonacciTask: public Poco::Task { public: FibonacciTask(int n): Task("FibonacciTask"), _n(n) {} void runTask() { long long a = 0, b = 1; _series.push_back(a); _series.push_back(b); for (int i = 2; i <= _n; i++) { long long temp = a + b; a = b; b = temp; _series.push_back(b); if (isCancelled()) { std::cout << "\nTask cancelled." << std::endl; break; } } for (const auto& num : _series) { std::cout << num << " "; } std::cout << std::endl; } void printSeries(){ for (const auto& num : _series) { std::cout << num << " "; } std::cout << std::endl; } private: int _n; std::vector<long long> _series; }; int main() { Poco::TaskManager tm; FibonacciTask *ft = new FibonacciTask(10); tm.start(ft); usleep(1000) ; ft->printSeries() ; usleep(1000) ; tm.joinAll(); usleep(1000) ; ft->printSeries() ; usleep(1000) ; return 0; }
问题原因
核心问题是POCO的TaskManager默认会在任务完成后自动删除Task对象。你在main里用new创建了FibonacciTask并传给tm.start(ft),但TaskManager在任务结束后会销毁这个Task实例,所以后续通过ft指针访问printSeries()时,已经是访问一个被释放的对象,属于未定义行为,才会出现乱码数据。
解决方法
方案一:禁止TaskManager自动删除Task对象
在调用start之前,调用tm.setAutoDelete(ft, false),这样TaskManager就不会自动销毁Task实例,你可以在后续手动管理内存(最后记得delete ft)。修改后的main函数:
int main() { Poco::TaskManager tm; FibonacciTask *ft = new FibonacciTask(10); tm.setAutoDelete(ft, false); // 禁止自动删除 tm.start(ft); usleep(1000) ; ft->printSeries() ; usleep(1000) ; tm.joinAll(); usleep(1000) ; ft->printSeries() ; usleep(1000) ; delete ft; // 手动释放内存 return 0; }
方案二:通过回调获取结果(推荐)
如果希望TaskManager托管Task的生命周期,可以在Task类中添加回调函数,在runTask结束时将结果传递给外部,避免直接访问已被销毁的对象:
#include <Poco/Task.h> #include <Poco/TaskManager.h> #include <iostream> #include <vector> #include <functional> class FibonacciTask: public Poco::Task { public: // 定义回调类型,用于传递结果 using ResultCallback = std::function<void(const std::vector<long long>&)>; FibonacciTask(int n, ResultCallback cb): Task("FibonacciTask"), _n(n), _cb(cb) {} void runTask() { long long a = 0, b = 1; _series.push_back(a); _series.push_back(b); for (int i = 2; i <= _n; i++) { long long temp = a + b; a = b; b = temp; _series.push_back(b); if (isCancelled()) { std::cout << "\nTask cancelled." << std::endl; break; } } // 任务完成时调用回调,传递结果 if (_cb) { _cb(_series); } for (const auto& num : _series) { std::cout << num << " "; } std::cout << std::endl; } private: int _n; std::vector<long long> _series; ResultCallback _cb; }; int main() { Poco::TaskManager tm; std::vector<long long> taskResult; // 定义回调函数,保存任务结果 auto resultCallback = [&taskResult](const std::vector<long long>& series) { taskResult = series; }; tm.start(new FibonacciTask(10, resultCallback)); tm.joinAll(); // 直接使用保存的结果 std::cout << "最终结果:"; for (const auto& num : taskResult) { std::cout << num << " "; } std::cout << std::endl; return 0; }
内容的提问来源于stack exchange,提问作者Joolsy
相关产品推荐
相关产品推荐

