如何将字符串类型的矢量元素作为参数传递给pthread_create()

How to pass a vector element of type string as argument to pthread_create()?

本文关键字:参数传递 pthread create 元素 字符串 类型      更新时间:2023-10-16

我正在尝试将字符串类型的矢量元素传递给pthread_create()函数。该消息未打印在输出中。我哪里错了?

#include <iostream>
#include <pthread.h>
#include <cstdlib>
#include <vector>
using namespace std;
#define NUM_THREADS 5
void *print_thread_details(void  *thread_no){
std::string str = *reinterpret_cast<std::string*>(thread_no);
cout<<"n Running thread = "<<str<<endl;
pthread_exit(NULL);
}
int main(){
/*initialize an array of pthreads*/
pthread_t threads[NUM_THREADS];
int rc;
vector<string> v(NUM_THREADS);
for(int i=0;i<NUM_THREADS;i++){
string s = "Thread No = ";
char temp = i+'0';
s=s+temp;
v.push_back(s);
rc = pthread_create(&threads[i], NULL, print_thread_details,&v[i] );
if (rc){
cout << "Error:unable to create thread," << rc << endl;
exit(-1);
}
}
pthread_exit(NULL);
return 0;
}

输出:

运行线程=

运行线程=

运行线程=

运行线程=

运行线程=

如何将字符串类型的矢量元素作为参数传递给pthread_create()?

您现在正是如何传递它们的。

但是,在线程处于活动状态时,必须小心防止字符串被破坏或移动。

输出中没有打印消息。

传递给线程的所有字符串都是空的。


我怀疑您对矢量的工作方式感到困惑:

vector<string> v(NUM_THREADS);

这构建了一个由5个元素组成的向量。5个字符串中的每一个都是空的。

v.push_back(s);

这增加了第六个。。。向量中的第10个元素。这些字符串不是空的,但也不会传递给线程,因为您使用了包含空字符串的索引0…4。

此外,这些推回可能会导致向量重新分配,在这种情况下,传递给先前创建的线程的指针将变得无效,从而导致未定义的行为。

您可能应该将其替换为:

v[i] = s;

另一种方法是从一个空向量开始,并在循环中推送生成的字符串。但在这种情况下,您必须预先保留内存,以避免指针因重新分配而失效。或者在启动任何线程之前,在单独的循环中填充向量。


PS。print_thread_details返回void*,但缺少返回语句。这种行为是不明确的。

问题是,您正在调用向量构造函数,该构造函数用空白字符串预先填充向量,然后将其他非空白字符串推到向量的末尾。矢量最终将包含10个字符串,而不是5个。但是线程将只看到空白字符串。

移除传递给向量构造函数的值,那么向量最初将为空。调用向量的reserve()方法来预分配向量,而不向其中实际添加项目:

vector<string> v;
v.reserve(NUM_THREADS);

否则,如果没有reserve(),对push_back()的每次调用都可能重新分配向量的内部区域,从而使任何现有的字符串指针无效,当您填充向量并同时创建线程时,这将是不好的。更安全的方法是在创建线程之前将所有字符串推入向量:

vector<string> v;
for(int i=0;i<NUM_THREADS;i++){
// consider using std::ostringstream instead...
string s = "Thread No = ";
char temp = i+'0';
s=s+temp;
v.push_back(s);
}
for(int i=0;i<NUM_THREADS;i++){
rc = pthread_create(&threads[i], NULL, print_thread_details,&v[i] );
...
}

附带说明的是,一旦启动线程,就需要等待它们终止,然后才允许main()退出,否则当线程仍在使用字符串值时,向量可能会被破坏。