我正在尝试将字符串类型向量元素传递给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;
}
输出:
正在运行thread =
正在运行thread =
正在运行thread =
正在运行thread =
正在运行thread =
答案 0 :(得分:1)
如何将string类型的vector元素作为参数传递给pthread_create()?
你现在正是如何传递它们的。
但是,在线程处于活动状态时,必须注意防止字符串被销毁或移动。
消息未在输出中打印。
传递给线程的所有字符串都是空的。
我怀疑你对矢量的工作方式感到困惑:
vector<string> v(NUM_THREADS);
这构造了5个元素的向量。 5个字符串中的每一个都是空的。
v.push_back(s);
这会在向量中添加第6个〜第10个元素。这些字符串不为空,但也不会传递给线程,因为您使用的索引0 ... 4包含空字符串。
此外,这些回退可能会导致向量重新分配,在这种情况下,传递给先前创建的线程的指针将变为无效,从而导致未定义的行为。
您应该将其替换为:
v[i] = s;
另一种方法是从空向量开始,并在循环中推送生成的字符串。但在这种情况下,您必须预先保留内存以避免由于重新分配而导致指针失效。或者在启动任何线程之前,在单独的循环中填充向量。
PS。 print_thread_details
返回void*
但缺少return语句。行为未定义。
答案 1 :(得分:1)
问题是你正在调用使用空字符串预填充向量的向量构造函数,然后你将其他非空字符串推送到向量的末尾。向量最终会有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()
退出,否则在线程仍在使用字符串值时可以销毁该向量。