gpt4 book ai didi

C++将多个线程的结果返回到数组中

转载 作者:搜寻专家 更新时间:2023-10-31 00:15:30 25 4
gpt4 key购买 nike

我有一个模式匹配程序,它将一个字符串作为输入并返回一个与字典紧密匹配的字符串。由于该算法需要几秒钟来运行一个匹配查询,因此我尝试使用多线程来运行批量查询。

我首先读入一个包含查询列表的文件,并为每个查询分派(dispatch)一个新线程来执行匹配算法,使用 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
}

结果声明为

// 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 threading templates,您会轻松很多而不是混合使用 C pthread 库和 C++。

关于C++将多个线程的结果返回到数组中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19232916/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com