Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何从无限循环外部杀死无限循环中的pthread?_C_Memory Leaks_Pthreads_Threadpool - Fatal编程技术网

C 如何从无限循环外部杀死无限循环中的pthread?

C 如何从无限循环外部杀死无限循环中的pthread?,c,memory-leaks,pthreads,threadpool,C,Memory Leaks,Pthreads,Threadpool,我创建了一个线程,并将其放入一个无限循环中。我在用valgrind检查代码时发现内存泄漏。这是我的密码: #include <pthread.h> #include <time.h> void thread_do(void){ while(1){} } int main(){ pthread_t th; pthread_create(&th, NULL, (void *)thread_do, NULL); sleep(2

我创建了一个线程,并将其放入一个无限循环中。我在用valgrind检查代码时发现内存泄漏。这是我的密码:

#include <pthread.h>
#include <time.h>

void thread_do(void){
    while(1){}
}

int main(){
    pthread_t th;   
    pthread_create(&th, NULL, (void *)thread_do, NULL);

    sleep(2);
    /* I want to kill thread here */
    sleep(2);
    return 0;
}
#包括
#包括
无效线程(无效){
而(1){}
}
int main(){
pthread_t th;
pthread_create(&th,NULL,(void*)thread_do,NULL);
睡眠(2);
/*我想在这里杀线*/
睡眠(2);
返回0;
}
因此,在main中创建了一个线程,该线程一直运行thread_do()。有没有办法在2秒后从主干道内杀死它?我已经尝试了
pthread\u detach(th)
pthread\u cancel(th)
,但仍然出现漏洞。

一些小想法:

  • 您正试图取消线程,但如果取消策略是针对延迟取消,则您的
    线程\u do()
    将永远不会被取消,因为它从不调用任何作为取消点的函数:
  • 线程的取消类型,由
    pthread_setcanceltype(3)可以是异步的,也可以是
    延迟(新线程的默认值)。异步的
    可取消性意味着线程可以随时取消
    时间(通常立即,但系统不保证
    这个)。延迟取消意味着取消将
    被延迟,直到线程下一次调用
    取消点。是或可能是的函数列表
    pthreads(7)中提供了取消点。
    
  • 您没有在简单的示例代码中加入线程;在程序结束前调用
    pthread\u join(3)
  • 在一个被取消的线程终止后
    使用pthread_join(3)的线程将pthread_作为
    线程的退出状态。(用螺纹连接是唯一的方法
    要知道取消已完成。)
    
    正如@sarnold指出的,默认情况下,如果不调用任何作为取消点的函数,就不能使用
    pthread\u cancel()
    取消线程。。。但这可以通过使用
    pthread\u setcanceltype()
    将线程的取消类型设置为异步而不是延迟来改变。为此,您需要添加类似于
    pthread\u setcanceltype(pthread\u CANCEL\u ASYNCHRONOUS,NULL)的内容在线程函数的开始附近,在开始循环之前。然后,您可以通过从
    main()
    调用
    pthread\u cancel(th)
    来终止线程

    但是请注意,以这种方式取消线程(无论异步与否)并不会清理线程函数中分配的任何资源(正如Kevin在评论中所指出的)。为了干净地执行此操作,您可以:

    • 确保线程在退出前不执行任何需要清理的操作(例如,使用
      malloc()
      分配缓冲区)
    • 确保在线程退出后,在其他地方的线程之后,您有一些清理方法
    • 使用
      pthread\u cleanup\u push()
      pthread\u cleanup\u pop()
      添加清理处理程序,以便在取消线程时清理资源。请注意,如果取消类型是异步的,这仍然是有风险的,因为线程可能会在分配资源和添加清理处理程序之间被取消
    • 避免使用
      pthread\u cancel()
      ,让线程检查一些条件以确定何时终止(这将在长时间运行的循环中进行检查)。由于线程随后会检查终止本身,因此它可以在检查后执行所需的任何清理
    实现最后一个选项的一种方法是使用互斥体作为标志,并使用封装在函数中的
    pthread\u mutex\u trylock()对其进行测试,以在循环测试中使用:

    #include <pthread.h>
    #include <unistd.h>
    #include <errno.h>
    
    /* Returns 1 (true) if the mutex is unlocked, which is the
     * thread's signal to terminate. 
     */
    int needQuit(pthread_mutex_t *mtx)
    {
      switch(pthread_mutex_trylock(mtx)) {
        case 0: /* if we got the lock, unlock and return 1 (true) */
          pthread_mutex_unlock(mtx);
          return 1;
        case EBUSY: /* return 0 (false) if the mutex was locked */
          return 0;
      }
      return 1;
    }
    
    /* Thread function, containing a loop that's infinite except that it checks for
     * termination with needQuit() 
     */
    void *thread_do(void *arg)
    {
      pthread_mutex_t *mx = arg;
      while( !needQuit(mx) ) {}
      return NULL;
    }
    
    int main(int argc, char *argv[])
    {
      pthread_t th;
      pthread_mutex_t mxq; /* mutex used as quit flag */
    
      /* init and lock the mutex before creating the thread.  As long as the
         mutex stays locked, the thread should keep running.  A pointer to the
         mutex is passed as the argument to the thread function. */
      pthread_mutex_init(&mxq,NULL);
      pthread_mutex_lock(&mxq);
      pthread_create(&th,NULL,thread_do,&mxq);
    
      sleep(2);
    
      /* unlock mxq to tell the thread to terminate, then join the thread */
      pthread_mutex_unlock(&mxq); 
      pthread_join(th,NULL);
    
      sleep(2);
      return 0;
    }
    
    #包括
    #包括
    #包括
    /*如果互斥锁已解锁,则返回1(true),这是
    *线程的终止信号。
    */
    int needQuit(pthread\u mutex\u t*mtx)
    {
    开关(pthread\u mutex\u trylock(mtx)){
    案例0:/*如果我们得到锁,解锁并返回1(true)*/
    pthread_mutex_unlock(mtx);
    返回1;
    case EBUSY:/*如果互斥锁被锁定,则返回0(false)*/
    返回0;
    }
    返回1;
    }
    /*线程函数,包含一个无限循环,但它检查
    *使用needQuit()终止
    */
    void*thread\u do(void*arg)
    {
    pthread_mutex_t*mx=arg;
    而(!needQuit(mx)){}
    返回NULL;
    }
    int main(int argc,char*argv[])
    {
    pthread_t th;
    pthread_mutex_t mxq;/*用作退出标志的互斥体*/
    /*在创建线程之前初始化并锁定互斥锁
    互斥锁保持锁定,线程应保持运行
    互斥量作为参数传递给线程函数*/
    pthread_mutex_init(&mxq,NULL);
    pthread_mutex_lock(&mxq);
    pthread_create(&th,NULL,thread_do,&mxq);
    睡眠(2);
    /*解锁mxq以通知线程终止,然后加入线程*/
    pthread_mutex_unlock(&mxq);
    pthread_join(th,NULL);
    睡眠(2);
    返回0;
    }
    

    如果线程未分离(默认情况下通常不分离),则应在停止线程后调用
    pthread\u join()
    。如果线程被分离,您不需要加入它,但是您不知道它何时终止(或者大约终止,除非您添加另一种方式来指示它的退出)。

    取消pthreads意味着线程没有机会清理它分配的任何内存。好的,我通过使用一个全局
    keepalive=1
    解决了这个问题。然后我将
    while(1)
    更改为
    while(keepalive)
    。现在要杀死线程,我只需将变量keepalive的值更改为0,瞧!要对多个pthread使用这个互斥解决方案,我需要每个线程一个互斥,对吗?在这种情况下,你会推荐这种解决方案吗?@RicardoCrudo不,只有一个互斥锁。。。如果
    needQuit()
    成功锁定它,它会在。。。只有
    main()。有我们的线索吗