[英]Correct way of passing pointer to another thread
我有2个函数, func1()
和func2()
。 func2
将字符数组作为输入。 这两个函数在不同的线程上运行。 我从func1
调用func2
。 当我将堆栈分配的数组传递给func2
,当我从func2()
内部打印数组时,我得到了垃圾值。 但是,当我将一个堆分配的数组传递给func2
,我在func2()
得到了正确的字符串,即
func2(char * char_array)
{
/* Some code */
cout<<char_array;
}
/ * 这不起作用(垃圾值打印在func2()中) * /
func1()
{
char array_of_char[SIZE];
memset(array_of_char,0,SIZE);
strncpy(array_of_char,"SOME_STRING",SIZE);
func2(array_of_char); //Asynchronous call to func2(). func1() proceeds immediately.
/*
some code
*/
}
/ * 起作用(正确的值在func2中打印) * /
func1()
{
char * array_of_char=new char[SIZE];
memset(array_of_char,0,SIZE);
strncpy(array_of_char,"SOME_STRING",SIZE);
func2(array_of_char); //Asynchronous call to func2(). func1() proceeds immediately.
/*
some code
*/
}
这是否意味着在多线程程序中,每当必须在不同线程之间传递某些指针时,该指针应始终指向堆分配的内存?
请注意,func2()实际上是在事件发生时执行的回调函数。 我已将这些细节隐藏在问题中。 Func1()不会停止/等待func2()的执行。
编辑 :我觉得我需要提供一些实现的更多细节。 在我的程序中,我正在使用Cassandra的Datastax C ++客户端库。 请在最后找到链接,其中包含程序中使用的功能的一些详细信息:
int main()
{
func1();
/* some code */
return 0;
}
/ * 这不起作用(垃圾在func2中打印) * /
void func1()
{
/* some code */
char array_of_char[SIZE];
memset(array_of_char,0,SIZE);
strncpy(array_of_char,"SOME_STRING",SIZE);
CassFuture* l_query_future = NULL;
/* some code where query is created */
l_query_future = cass_session_execute(rtGetSession(), l_stmt); //l_stmt is the query statement, rtgetSession() returns CassSession *
cass_future_set_callback ( l_query_future, func2, (void *)array_of_char); //details in the link given in the end
/* some code */
}
/ * 起作用(正确的值在func2中打印) * /
void func1()
{
/* some code */
char * array_of_char=new char[SIZE];
memset(array_of_char,0,SIZE);
strncpy(array_of_char,"SOME_STRING",SIZE);
CassFuture* l_query_future = NULL;
/* some code where query is created */
l_query_future = cass_session_execute(rtGetSession(), l_stmt); //l_stmt is the query statement, rtgetSession() returns CassSession *
cass_future_set_callback ( l_query_future, func2, (void *)array_of_char);
/*
some code
*/
}
void func2(CassFuture* l_query_future, void * data)
{
/* some code */
cout<<(char *)data;
}
Datastax驱动程序API的参考:
如何在不同的线程下运行func1()和func2()? func1()直接调用func2(),因此它们在同一线程下运行。 即使func1()的第一个实现也应该起作用,因为该数组仍在该位置。
编辑:
但是,直接从func1()内部调用func2()并不是“异步调用func2()”(即使在其他时候它被用作线程函数)。 “异步调用”意味着使用func2()作为线程函数创建一个新线程。 如果是这样,则非常希望得到这种行为,因为func1()在func2()运行时可能已经退出,并且那时该数组将不存在。 另一方面,堆块仍将被分配,因此它将起作用。 func2()应该然后释放该块。
编辑2:
嗯,是的,第二个版本确实是“对func2()的异步调用”,因此上面列出的对象的生命周期注意事项确实适用。
这是否意味着在多线程程序中,每当必须在不同线程之间传递某些指针时,该指针应始终指向堆分配的内存?
否。这意味着您必须正确跟踪对象的生命周期。 当线程1完成执行时,堆栈将被自动清理,从而破坏了线程2处理的结果。 另一方面,如果未显式释放,则堆内存将保留。 您必须在线程1中检查线程2是否仍在执行,并等待线程2完成,例如使用join
函数。
不,指针不必指向堆分配的内存,但是必须确保在加入线程之前该内存(在这种情况下为数组)将可用。
在这种情况下,在不起作用的版本中,数组分配在堆栈上,而函数func1
完成后,数组将被销毁。 因此,垃圾价值-可能是在那个地址上已经写了一些东西。
要解决此问题,您可以等到func1
的线程完成。 在这种情况下,局部变量可以。
此代码在堆栈上分配的数组上运行良好。 如前所述,这里绝对没有线程发生。 但是要回答您的问题,当在不同线程之间(实际使用它们时)传递指针(或其他数据)时,您可能需要某种同步,例如互斥锁或原子,并且当然要确保任何数据的生命周期。
这是您的代码,
#include <iostream>
#include <cstring>
using namespace std;
#define SIZE 20
void func2(char * char_array)
{
/* Some code */
cout<<char_array;
}
void func1()
{
char array_of_char[SIZE];
strncpy(array_of_char,"SOME_STRING",SIZE);
func2(array_of_char);
}
int main() {
func1();
return 0;
}
我应该注意,您正在通过将SIZE大小复制到数组中来复制其他垃圾,您实际上只想复制strlen(“ SOME_STRING”)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.