我需要创建计算文件夹中文件的控制台应用程序。每个文件夹执行并行。我从.txt文件获取目录路径并将它们放到线程中。
我使用std :: thread和boost :: filesystem。
它适用于一个目录,但崩溃或返回错误的结果很多。 有趣的是,最后一个线程总是得到正确的结果,但之前的那些是错误的。
这是我的代码:
DirHandler.h
#include <iostream>
#include <fstream>
#include <string>
#include <thread>
#include <windows.h>
#include <boost/filesystem.hpp>
using namespace std;
using namespace boost::filesystem;
class DirHandler{
public:
DirHandler();
void getPaths(ifstream file);
void output();
static void run_thread(pair<string, int> * dir, string cur_path, void *args)
{
DirHandler *prunnable = static_cast<DirHandler*>(args);
prunnable->some_counting(dir, cur_path);
}
private:
vector<thread> threads;
vector<pair<string, int>> paths; // current directory name and files amount
void some_counting(pair<string, int> * dir, string cur_path);
void escape();
};
DirHandler.cpp
void DirHandler::getPaths(ifstream file)
{
// parse pathes and create separate thread for each
string line;
if (file.is_open())
{
while (getline(file, line))
{
cout << line << endl;
// add thread for path
pair<string, int> dir = make_pair(line, 0);
paths.push_back(dir);
threads.push_back(thread(&DirHandler::run_thread, &paths.back(), line, this));
}
for (auto& thr : threads){
thr.join();
}
file.close();
}
}
void DirHandler::some_counting(pair<string, int> * dir, string cur_path){...}
的main.cpp
#include <iostream>
#include <windows.h>
#include "DirHandler.h"
int main(int argc, char* argv[])
{
DirHandler dirHandler = DirHandler();
dirHandler.getPaths(ifstream("strings.txt")); //ifstream(argv[1])
dirHandler.output();
return 0;
}
注意:调试时我发现最后的所有流最后都有id = 0
此外,我已经读过该问题可能是由对单个对象的引用引起的。 (就我而言,它是vector<pair<string, int>> paths
)
所以我的问题是如何让几个线程正常工作?
答案 0 :(得分:2)
问题是你从paths
向量得到指针,如果向量被调整大小,所有先前的指针(和迭代器)到向量中的元素都将变为无效。使用无效指针会导致undefined behavior,这通常会导致崩溃。
造成矢量的一种常见方法是向其中添加新元素,这正是您在循环中所做的。
一种解决方案是将对向量的引用和元素的索引传递给线程(索引在重新分配时不会更改)。另一个解决方案是有两个循环,一个用于将所有元素添加到向量中,第二个用于创建线程。
还有其他解决方案,例如不将指针传递给线程,而是通过值传递对。这实际上是我推荐的解决方案。
稍微检查一下你的代码之后,我也看到了,因为你使用std::thread
,根本不需要静态成员函数包装器。相反,您可以直接调用非静态实际线程函数:
threads.emplace_back(&DirHandler::some_counting, this, paths.back(), line);
[注意使用this
作为第二个参数,以及emplace_back
向量的更改threads
答案 1 :(得分:0)
嗯,最明显的问题是: socket.on('newdata', function(d){
var output = document.getElementById('output');
output.innerHTML = d;
})
你正在使用指向对象(threads.push_back(thread(&DirHandler::run_thread, &paths.back(), line, this));
)的指针,它可能在&paths.back()
之后不再存在。因此,应该修复此错误,您不能将指针传递给push_back
项,除非您可以保证它不会重新分配其内部结构。
除了那些丑陋的代码,我什么也看不见。但vector
方法可能潜伏着更多问题。