在 Linux 中使用多线程的概率很高,关于 pthread_create 函数传参的问题,需要注意下面几个点:
测试源码:
#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;
}
如上内容为个人看法,若有不足之处敬请指教。