繁体   English   中英

将指针传递到另一个线程的正确方法

[英]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的参考:

  1. cass_future_set_callback
  2. 卡斯未来
  3. CassSession
  4. cass_session_execute

如何在不同的线程下运行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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM