pthread_create传参问题

2020-08-31  本文已影响0人  大爷来了啊

回顾下多线程基础,随手写了个bug。

#include <unistd.h>
#include <pthread.h>
#include <stdio.h>

const int MAXNUM = 10;

void *func(void  *arg)
{
    int *pInt = (int *)arg;
    printf("pthread_id = %ld, arg = %d\n",pthread_self(),*pInt);
}

int main(int argc,char *argv[])
{
    pthread_t pthreads[MAXNUM];
    for(int i = 1;i <= MAXNUM;i++)
    {
        pthread_create(&pthreads[i],NULL,func,(void *)&i);
    }
    sleep(2);
    for(int i = 1;i <= MAXNUM;i++)
    {
        pthread_join(pthreads[i],NULL);
    }
}

编译:gcc -lpthread main.c -o main
出错:

对‘pthread_create’未定义的引用 
对‘pthread_join’未定义的引用
collect2: error: ld returned 1 exit status

把链接库换个位置 gcc main.c -o main -lpthread,这样就行了,Ubuntu真操蛋。
运行下试试:

捕获.PNG
嗯?
为啥?
出错了?
找谁背锅?

问题出在了传参上,so加个打印参数地址瞅瞅。

    printf("arg address = %p\n",arg);

搞一把:

捕获.PNG
地址都一样,为啥呢?

其实问题出在了传参方式上,对所有线程来说它们公用 i的地址。在线程创建的时候并非先创建的就一定先执行,后创建的进程可能会把 i的值修改掉,所以导致在运行函数中去取 i的值是不准确的。

改进

方案一:(void *)&i ===> (void *)i;

搞一把:


捕获.PNG

gdb登场

捕获.PNG
问题一目了然,非法访问内存,这个解决方案有点拍脑袋了。
方案二:
    int *tmp = (int *)malloc(sizeof(int));
    *tmp = i;
    (void *)&i ===> (void*)tmp;

搞一把:


捕获.PNG

嗯,这回正常了,不过要记得有个malloc没有释放。

总结

就算是拍脑袋也要搞一把

上一篇 下一篇

猜你喜欢

热点阅读