这主要是关于范围和线程的问题。假设我们有以下结构。
struct Test
{
int number;
std::string name;
};
此结构的实例将用作pthread_create函数中的参数。以下是这可能是什么样子的一个例子。
pthread_t tid[5];
for(int i = 0; i < 5; ++i)
{
Test test;
test.number = 5;
test.name = "test";
pthread_create(&tid[i], NULL, func, (void *)&test);
}
这可以接受吗?由于test是在for的范围内声明的,这意味着我们只能在for循环的单次迭代中依赖它。
当调用pthread_create时,指向test的指针作为参数给出。这意味着func正在接收传递给pthread_create的相同指针。这意味着当测试超出范围时,我们不能再依赖于指向测试的指针。如果我们要创建更多本地,从而更改堆栈,指针指向的位置将被这些新本地人覆盖。它是否正确?
答案 0 :(得分:4)
这可以接受吗?
总的来说,不,因为你说的原因。具体来说,线程的入口函数可能在Test对象被销毁之后才开始执行,或者在线程的入口函数仍在使用它时可能会销毁Test对象。这些可能性中的任何一种都会导致未定义的行为(以及“有时”只能正常工作的程序)。
只要线程需要使用它,您需要保证传递给线程的数据保持有效。一种方法是在堆上分配该Test对象,并在Test-pointer完成后使用它调用delete
。或者,您可以使用条件变量来“暂停”主线程,直到子pthread发出信号表明它已经完成访问主线程堆栈上的Test,这样现在主线程可以继续执行。
如果我们要创建更多本地,那么改变堆栈, 指针指向的位置将被那些新的覆盖 当地人。这是对的吗?
是的,您正确理解了这个问题。