C++ 将结果从多个线程返回到数组中
C++ Returning results from several threads into an array
>我有一个模式匹配程序,它将一个字符串作为输入,并返回一个与字典紧密匹配的字符串。由于该算法需要几秒钟才能运行一个匹配查询,因此我尝试使用多线程来运行批处理查询。
我首先读取一个包含查询列表的文件,然后为每个查询调度一个新线程来执行匹配算法,使用 pthread_join 将结果返回到数组中。
但是,我得到了一些不一致的结果。例如,如果我的查询文件包含术语"红色、绿色、蓝色",则可能会收到"红色、绿色、绿色"作为结果。另一次运行可能会生成正确的"红色、绿色、蓝色"结果。它似乎有时会在数组中写入结果,但是为什么会发生这种情况,因为数组值是根据线程 id 设置的?
Dictionary dict; // global, which performs the matching algorithm
void *match_worker(void *arg) {
char* temp = (char *)arg;
string strTemp(temp);
string result = dict.match(strTemp);
return (void *)(result.c_str());
}
void run(const string& queryFilename) {
// read in query file
vector<string> queries;
ifstream inquery(queryFilename.c_str());
string line;
while (getline(inquery, line)) {
queries.push_back(line);
}
inquery.close();
pthread_t threads[queries.size()];
void *results[queries.size()];
int rc;
size_t i;
for (i = 0; i < queries.size(); i++) {
rc = pthread_create(&threads[i], NULL, match_worker, (void *)(queries[i].c_str()));
if (rc) {
cout << "Failed pthread_create" << endl;
exit(1);
}
}
for (i = 0; i < queries.size(); i++) {
rc = pthread_join(threads[i], &results[i]);
if (rc) {
cout << "Failed pthread_join" << endl;
exit(1);
}
}
for (i = 0; i < queries.size(); i++) {
cout << (char *)results[i] << endl;
}
}
int main(int argc, char* argv[]) {
string queryFilename = arg[1];
dict.init();
run(queryFilename);
return 0;
}
编辑:按照Zac的建议,我修改了线程以明确地将结果放在堆上:
void *match_worker(void *arg) {
char* temp = (char *)arg;
string strTemp(temp);
int numResults = 1;
cout << "perform match for " << strTemp << endl;
string result = dict.match(strTemp, numResults);
string* tmpResult = new string(result);
return (void *)((*tmpResult).c_str());
}
虽然,在这种情况下,我会把删除调用放在哪里?如果我尝试将以下内容放在 run(( 函数的末尾,它会给出无效的指针错误。
for (i = 0; i < queries.size(); i++) {
delete (char*)results[i];
}
如果不调试它,我的猜测是它与以下内容有关:
void *match_worker(void *arg)
{
char* temp = (char *)arg;
string strTemp(temp);
string result = dict.match(strTemp); // create an automatic
return (void *)(result.c_str()); // return the automatic ... but it gets destructed right after this!
}
因此,当下一个线程运行时,它会写入您指向的同一内存位置(偶然(,并且您插入相同的值两次(而不是写入它(。
您应该将结果放在堆上,以确保在线程退出和将其存储在主线程中之间它不会被销毁。
通过您的编辑,您试图将事情混淆得有点太多。 我已经在下面修复了它:
void *match_worker(void *arg)
{
char* temp = (char *)arg;
string strTemp(temp);
int numResults = 1;
cout << "perform match for " << strTemp << endl;
string result = dict.match(strTemp, numResults);
string* tmpResult = new string(result);
return (void *)(tmpResult); // just return the pointer to the std::string object
}
将results
声明为
// this shouldn't compile
//void* results[queries.size()];
std::string** results = new std::string[queries.size()];
for (int i = 0; i < queries.size(); ++i)
{
results[i] = NULL; // initialize pointers in the array
}
清理内存时:
for (i = 0; i < queries.size(); i++)
{
delete results[i];
}
delete [] results; // delete the results array
也就是说,如果您使用 C++11 线程模板而不是混合使用 C pthread 库和C++,您将更容易。
该问题是由局部变量result
的生存期和成员函数返回的数据引起的 result.c_str()
。通过将 C 与 C++ 混合,可以使此任务变得不必要。请考虑使用 C++11 及其线程库。它使任务变得更加容易:
std::string match_worker(const std::string& query);
void run(const std::vector<std::string>& queries)
{
std::vector<std::future<std::string>> results;
results.reserve(queries.size());
for (auto& query : queries)
results.emplace_back(
std::async(std::launch::async, match_worker, query));
for (auto& result : results)
std::cout << result.get() << 'n';
}
相关文章:
- 从 C++ 中的函数返回数组地址问题
- 如何在 c++ 函数中返回数组
- 如何从 c++ 中的函数返回数组
- 为什么 c++ 函数可以正确返回数组的大小?
- 解释通过从函数引用返回数组的语法
- (C++)我的函数不返回数组
- 如何按 C++ 中的值从函数返回数组
- 返回数组中值的指针地址
- 创建一个函数来转换数组元素的类型并返回数组的地址
- 使用数组类返回数组c++
- 如何使函数返回数组?用于制作在VB.NET中使用的DLL
- 从函数 BY VALUE 返回数组,返回结构时会发生什么?
- 调用和打印函数,在 C++ 中返回数组
- 如何使用递归函数返回数组中整数的索引?
- 从函数返回数组时是否需要删除
- 为什么从函数返回数组时需要将数组声明为静态数组.(C++)
- C++返回数组而不进行动态内存分配?
- 在函数 c++ 中返回数组时出现问题
- 如何从C 中的函数返回数组
- 如何使类函数返回数组,然后将其调用并存储在 main 中