Linux多线程编程pthread_create传参的问题

在 Linux 中使用多线程的概率很高,关于 pthread_create 函数传参的问题,需要注意下面几个点:

  1. 参数不为局部变量的地址;
  2. 传入的参数为值类型时,可能会出现警告,如64位系统,传入 int 类型的值;
  3. 建议传入静态变量的地址,或动态分配的内存地址(注意:需要自己手动释放);
  4. 若需要传入值类型的参数时,定义与 void * 长度一致的值类型,如32位系统的 int 类型,或64位系统的 long 类型。

测试源码:

#include 
#include 
#include 

#define TEST_MODE	1

static void *PthreadTest(void *arg)
{
#if TEST_MODE > 0
	int param = (int)(arg);
#else
	int param = *((int *)(arg));
#endif

	printf("param: %d\n", param);
	
	return NULL;
}

static void TestFunc(void)
{
	int arg = 10;
	pthread_t thread;
	pthread_attr_t threadAttr;

	pthread_attr_init(&threadAttr);
	pthread_attr_setdetachstate(&threadAttr, PTHREAD_CREATE_DETACHED);			/* 设置分离属性 */
#if TEST_MODE > 0
	pthread_create(&thread, &threadAttr, PthreadTest, (void *)arg);				/* 传局部变量的值 */
#else
	pthread_create(&thread, &threadAttr, PthreadTest, (void *)&arg);					/* 传局部变量的地址 */
#endif
	pthread_attr_destroy(&threadAttr);
}

int main(void)
{
	TestFunc();
	sleep(1);																	/* 等待线程运行起来 */
	printf("sizeof(void *): %ld, sizeof(int *): %ld, sizeof(int): %ld\n", sizeof(void *), sizeof(int *), sizeof(int));
	
	return 0;
}

编译:

gcc -o test test.c -pthread

当 TEST_MODE 为 0 时,不会发生警告;当 TEST_MODE 为 1 时,提示如下警告:

test.c: In function ‘PthreadTest’:
test.c:10:14: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
  int param = (int)(arg);
              ^
test.c: In function ‘TestFunc’:
test.c:29:52: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
  pthread_create(&thread, &threadAttr, PthreadTest, (void *)arg);    /* 传局部变量的值 */

TEST_MODE 为 0 和 1 时,运行结果都一样,如下:

param: 10

结论

从上述结果来看,执行结果并没有出现异常,但是在项目中,当传入线程的参数为局部变量的地址时,由于函数结束后会回收该地址,如果又重新分配给其他变量使用,这时候就会出现值异常。

所以 pthread_create 传参时,需要注意不传入局部变量的地址。

但是我们传入值时,此时编译会出现报警,提示:从指针强制转换为不同大小的整数,这是由于void * 和 int 类型的长度是不一致的,我们可以通过打印 sizeof(void *) 和 sizeof(int) 来验证(64位系统)。发现 void * 是8个字节,int 是4个字节。

所以在传参时可以传入静态变量的地址或动态分配的内存地址,这样就可以避免值异常和不同长度的类型之间的转换。同时,也可以定义与指针类型相同长度的整数类型,这样传值就不会出现警告。如上述测试代码进行修改,如下:

#include 
#include 
#include 

static void *PthreadTest(void *arg)
{
	long param = (long)(arg);

	printf("param: %ld\n", param);
	
	return NULL;
}

static void TestFunc(void)
{
	long arg = 10;
	pthread_t thread;
	pthread_attr_t threadAttr;

	pthread_attr_init(&threadAttr);
	pthread_attr_setdetachstate(&threadAttr, PTHREAD_CREATE_DETACHED);			/* 设置分离属性 */
	pthread_create(&thread, &threadAttr, PthreadTest, (void *)arg);				/* 传局部变量的值 */
	pthread_attr_destroy(&threadAttr);
}

int main(void)
{
	TestFunc();
	sleep(1);																	/* 等待线程运行起来 */
	printf("sizeof(void *): %ld, sizeof(int *): %ld, sizeof(int): %ld\n", sizeof(void *), sizeof(int *), sizeof(int));
	
	return 0;
}

当然也可以使用强制类型转换解决报警的问题,如下:

#include 
#include 
#include 

static void *PthreadTest(void *arg)
{
	int param = (int)(long)(arg);

	printf("param: %ld\n", param);
	
	return NULL;
}

static void TestFunc(void)
{
	int arg = 10;
	pthread_t thread;
	pthread_attr_t threadAttr;

	pthread_attr_init(&threadAttr);
	pthread_attr_setdetachstate(&threadAttr, PTHREAD_CREATE_DETACHED);			/* 设置分离属性 */
	pthread_create(&thread, &threadAttr, PthreadTest, (void *)(long)arg);				/* 传局部变量的值 */
	pthread_attr_destroy(&threadAttr);
}

int main(void)
{
	TestFunc();
	sleep(1);																	/* 等待线程运行起来 */
	printf("sizeof(void *): %ld, sizeof(int *): %ld, sizeof(int): %ld\n", sizeof(void *), sizeof(int *), sizeof(int));
	
	return 0;
}

如上内容为个人看法,若有不足之处敬请指教。

你可能感兴趣的:(Linux,C,linux,c语言)