具有 C++ 线程的并行字典破解器
Parallel dictionary cracker with c++ threads
我正在学习更好地使用 C++ 中的线程,这是我的学期末作业。我正在尝试创建一个相当简单的字典破解程序,它接受一个 .txt 文件并将每个单词复制到一个向量中;该向量被分成 "sectors" 等长(每个扇区的单词数)以便并行化。然后程序启动将 2 个迭代器作为参数的线程,指向一个扇区的开始和结束。每个线程在构造时将处理紧跟前一个的扇区。
因此,线程函数将遍历开始迭代器和结束迭代器之间的向量扇区的每个字,计算它的散列值,并将它与我需要破解的密码的散列值进行比较。我在实际访问迭代器指向的特定单词时使用了互斥体,尽管我不完全确定这是否是正确的方法。
目前,我的问题是出现了 2 个编译错误:
Error C2672 'std::invoke': no matching overloaded function found DictionaryCrackerEC d:\programs\microsoft visual studio 14.0\vc\include\thr\xthread 240
Error C2893 Failed to specialize function template 'unknown-type std::invoke(_Callable &&,_Types &&...)' DictionaryCrackerEC d:\programs\microsoft visual studio 14.0\vc\include\thr\xthread 240
而且我不知道它们到底来自哪一行,也不知道如何解决。我在网上调查了各种 "invoke" 问题,但我要么不理解它们,要么它们似乎与 类 成员函数调用和类似的东西有关,而我什至没有 类 在我的程序中。
这就是理论,这是我主要的实际代码:
#include <iostream>
#include <vector>
#include <string>
#include <thread>
#include <mutex>
#include <fstream>
#include <chrono>
#include <Windows.h>
#include <assert.h>
#include <openssl\md5.h>
using namespace std;
//determine the best number of threads based on hardware
const int PC_THREADS_NUM = thread::hardware_concurrency();
mutex password_mutex;
int main()
{
vector<string> passwdVector;
vector<string>::const_iterator beginIter, endIter;
passwdVector.reserve(18000);
//code here that loads words from .txt file into passwdVector
string userPassword = "";
cout << "please insert the password that you'd like to crack: ";
cin >> userPassword;
//splitting the vector into sections to parallelize
int sectionLength = passwdVector.size() / PC_THREADS_NUM;
beginIter = passwdVector.begin();
endIter = beginIter + sectionLength;
vector<thread*> sliceHashingThreads;
for (int i = 0; i < PC_THREADS_NUM; i++)
{
sliceHashingThreads.push_back(new thread(sliceHashCompare, std::ref(passwdVector), userPassword, beginIter, endIter, i));
beginIter = endIter + 1;
endIter += sectionLength;
}
for (int i = 0; i < sliceHashingThreads.size(); i++)
{
sliceHashingThreads[i]->join();
}
system("PAUSE");
return 0;
}
这里是 sliceHashCoompare 函数:
void sliceHashCompare(vector<string>& passwordList, string& password, vector<string>::const_iterator beginIter, vector<string>::const_iterator endIter, int& threadID)
{
string vectorElement = "", hashedElement = "";
bool isPassFound = false;
while (isPassFound != true)
{
for (; beginIter <= endIter; ++beginIter)
{
password_mutex.lock();
vectorElement = *beginIter;
password_mutex.unlock();
cout << threadID << " is processing word: " << vectorElement << endl;
//Sleep(100);
hashedElement = md5Hash(vectorElement);
if(hashedElement == md5Hash(password))
{
isPassFound = true;
cout << "The password was found! " << password << endl;
cout << "Hash value: " << hashedElement << endl;
}
}
if(isPassFound == false)
{
cout << "Password not found in the dictionary" << endl;
break;
}
}
}
找到密码后,我想我需要一个条件变量来停止所有其他线程。我正在考虑的另一件事是稍后实现一个 farmer/worker 系统,它将向量分成更多更小的扇区,并有一个任务队列,以便在线程完成时继续为线程工作。但是现在我坚持使用 8 个线程 (thread::hardware_concurrency) 并且有些东西运行良好,我只会在之后进行改进。但非常感谢任何提示、建议和解释,因为我正在学习。
真的希望有人能向我解释出了什么问题,让我明白如何解决它以及为什么。非常感谢您的帮助!
我可以看到两个主要问题 - 你不能复制 std::thread,但你可以移动它,所以将它移动到你的向量中
sliceHashingThreads.push_back(
std::move(new thread(sliceHashCompare,
std::ref(passwdVector),
userPassword,
beginIter,
endIter,
i)));
此外,请注意,如果您只是尝试调用您的函数,
sliceHashCompare(std::ref(passwdVector), userPassword, beginIter, endIter, 0);
你也会得到一个错误——因为它以threadID作为ref,如果你把它改成int threadID
就可以了。
VS 给出了一个 "user friendly" 错误列表,但是如果您查看完整的输出(在视图 | 输出下找到),如果它还没有打开,那么搜索错误直到它提到您的代码。
现在应该可以编译 link。不过你还有其他问题。谁会删除你的话题?参见例如
当然,你不需要将指针移动到线程;问题是 int &
(并没有删除指针)。
您可以通过使用 std::move
或
来使用 std::vector<std::thread>
sliceHashingThreads.emplace_back(sliceHashCompare,
std::ref(passwdVector),
userPassword, beginIter, endIter, i);
您也可以使用 std::ref(i)
作为最后一个参数,以避免更改 sliceHashCompare
函数。
我正在学习更好地使用 C++ 中的线程,这是我的学期末作业。我正在尝试创建一个相当简单的字典破解程序,它接受一个 .txt 文件并将每个单词复制到一个向量中;该向量被分成 "sectors" 等长(每个扇区的单词数)以便并行化。然后程序启动将 2 个迭代器作为参数的线程,指向一个扇区的开始和结束。每个线程在构造时将处理紧跟前一个的扇区。
因此,线程函数将遍历开始迭代器和结束迭代器之间的向量扇区的每个字,计算它的散列值,并将它与我需要破解的密码的散列值进行比较。我在实际访问迭代器指向的特定单词时使用了互斥体,尽管我不完全确定这是否是正确的方法。
目前,我的问题是出现了 2 个编译错误:
Error C2672 'std::invoke': no matching overloaded function found DictionaryCrackerEC d:\programs\microsoft visual studio 14.0\vc\include\thr\xthread 240
Error C2893 Failed to specialize function template 'unknown-type std::invoke(_Callable &&,_Types &&...)' DictionaryCrackerEC d:\programs\microsoft visual studio 14.0\vc\include\thr\xthread 240
而且我不知道它们到底来自哪一行,也不知道如何解决。我在网上调查了各种 "invoke" 问题,但我要么不理解它们,要么它们似乎与 类 成员函数调用和类似的东西有关,而我什至没有 类 在我的程序中。
这就是理论,这是我主要的实际代码:
#include <iostream>
#include <vector>
#include <string>
#include <thread>
#include <mutex>
#include <fstream>
#include <chrono>
#include <Windows.h>
#include <assert.h>
#include <openssl\md5.h>
using namespace std;
//determine the best number of threads based on hardware
const int PC_THREADS_NUM = thread::hardware_concurrency();
mutex password_mutex;
int main()
{
vector<string> passwdVector;
vector<string>::const_iterator beginIter, endIter;
passwdVector.reserve(18000);
//code here that loads words from .txt file into passwdVector
string userPassword = "";
cout << "please insert the password that you'd like to crack: ";
cin >> userPassword;
//splitting the vector into sections to parallelize
int sectionLength = passwdVector.size() / PC_THREADS_NUM;
beginIter = passwdVector.begin();
endIter = beginIter + sectionLength;
vector<thread*> sliceHashingThreads;
for (int i = 0; i < PC_THREADS_NUM; i++)
{
sliceHashingThreads.push_back(new thread(sliceHashCompare, std::ref(passwdVector), userPassword, beginIter, endIter, i));
beginIter = endIter + 1;
endIter += sectionLength;
}
for (int i = 0; i < sliceHashingThreads.size(); i++)
{
sliceHashingThreads[i]->join();
}
system("PAUSE");
return 0;
}
这里是 sliceHashCoompare 函数:
void sliceHashCompare(vector<string>& passwordList, string& password, vector<string>::const_iterator beginIter, vector<string>::const_iterator endIter, int& threadID)
{
string vectorElement = "", hashedElement = "";
bool isPassFound = false;
while (isPassFound != true)
{
for (; beginIter <= endIter; ++beginIter)
{
password_mutex.lock();
vectorElement = *beginIter;
password_mutex.unlock();
cout << threadID << " is processing word: " << vectorElement << endl;
//Sleep(100);
hashedElement = md5Hash(vectorElement);
if(hashedElement == md5Hash(password))
{
isPassFound = true;
cout << "The password was found! " << password << endl;
cout << "Hash value: " << hashedElement << endl;
}
}
if(isPassFound == false)
{
cout << "Password not found in the dictionary" << endl;
break;
}
}
}
找到密码后,我想我需要一个条件变量来停止所有其他线程。我正在考虑的另一件事是稍后实现一个 farmer/worker 系统,它将向量分成更多更小的扇区,并有一个任务队列,以便在线程完成时继续为线程工作。但是现在我坚持使用 8 个线程 (thread::hardware_concurrency) 并且有些东西运行良好,我只会在之后进行改进。但非常感谢任何提示、建议和解释,因为我正在学习。
真的希望有人能向我解释出了什么问题,让我明白如何解决它以及为什么。非常感谢您的帮助!
我可以看到两个主要问题 - 你不能复制 std::thread,但你可以移动它,所以将它移动到你的向量中
sliceHashingThreads.push_back(
std::move(new thread(sliceHashCompare,
std::ref(passwdVector),
userPassword,
beginIter,
endIter,
i)));
此外,请注意,如果您只是尝试调用您的函数,
sliceHashCompare(std::ref(passwdVector), userPassword, beginIter, endIter, 0);
你也会得到一个错误——因为它以threadID作为ref,如果你把它改成int threadID
就可以了。
VS 给出了一个 "user friendly" 错误列表,但是如果您查看完整的输出(在视图 | 输出下找到),如果它还没有打开,那么搜索错误直到它提到您的代码。
现在应该可以编译 link。不过你还有其他问题。谁会删除你的话题?参见例如
当然,你不需要将指针移动到线程;问题是 int &
(并没有删除指针)。
您可以通过使用 std::move
或
std::vector<std::thread>
sliceHashingThreads.emplace_back(sliceHashCompare,
std::ref(passwdVector),
userPassword, beginIter, endIter, i);
您也可以使用 std::ref(i)
作为最后一个参数,以避免更改 sliceHashCompare
函数。