我有两个功能,func1()
和func2()
。 func2
将字符数组作为输入。两个函数都在不同的线程上运行我从func2
致电func1
。当我将堆栈分配的数组传递给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的参考:
答案 0 :(得分:3)
如何在不同的线程下运行func1()和func2()? func1()直接调用func2(),因此它们在同一个线程下运行。即使func1()的第一个实现也应该有效,因为数组仍然存在。
编辑:
但是直接从func1()中调用func2()不是“对func2()的异步调用”(即使在某些其他方面它被用作线程函数)。 “异步调用”意味着使用func2()作为线程函数创建一个新线程。如果是这样,非常期望这种行为,因为当func2()运行时func1()可能已经退出,并且该数组在那时不存在。另一方面,仍将分配堆块,因此这将起作用。 func2()应该释放块。
EDIT2:
嗯,是的,第二个版本确实是“对func2()的异步调用”,因此上面列出的对象的生命周期考虑确实适用。
答案 1 :(得分:2)
这是否意味着在多线程程序中,每当必须在不同线程之间传递某个指针时,指针应始终指向堆分配的内存?
没有。这意味着您必须正确跟踪对象的生命周期。当线程1完成执行时,堆栈将自动清理,从而破坏线程2正在使用的结果。另一方面堆内存如果没有明确释放则保持不变。您必须在线程1中检查线程2是否仍在执行并等到它完成,例如使用join
函数。
答案 2 :(得分:2)
不,指针不必指向堆分配的内存,但是必须确保在加入线程之前内存(在本例中为数组)可用。
这里,在不起作用的版本中,数组在堆栈上分配,当函数func1
完成时,它被销毁。因此,垃圾价值 - 可能是在该地址写的东西已经准备好了。
要解决此问题,您可以等到线程在func1
完成。在这种情况下,局部变量就可以了。
答案 3 :(得分:2)
此代码可以在堆栈上分配的数组中正常运行。如前所述,这里绝对没有发生任何线程。要回答你的问题,当在不同线程之间传递指针(或其他数据)时(当你实际使用它们时),你可能需要某种同步,例如互斥或原子,当然还要确保任何数据的生命周期。
这是你的代码工作,
#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;
}
我应该注意到你是通过strncpy'ing SIZE复制额外的垃圾进入数组,你真的只想复制strlen(“SOME_STRING”)。