1. 程式人生 > >pthread_exit/pthread_kill之後局部對象之析構

pthread_exit/pthread_kill之後局部對象之析構

size 變量 系統 興趣 殺死 依然 print 使用 單獨

一、多線程與析構函數
這個是在C++編碼中可能存在的一個問題,假設說一個線程執行了局部變量的構造函數之後,沒有退出局部對象作用域之前,它主動退出線程(pthread_exit)或者被動退出線程(pthread_kill ed),那麽這個局部變量的析構函數是否會執行?這個問題對於通常的程序來說影響並不大,但是對於某些依賴在析構函數中執行復雜的系統級對象操作來說是比較重要的(例如釋放系統級的信號量,寫文件等),並且現在的C庫pthread_cleanup_XXX函數實現也依賴於這個特性,所以這裏簡單單獨描述一些。
二、測試代碼
[tsecer@Harry pthreadexit]$ ls
main.c Makefile

[tsecer@Harry pthreadexit]$ cat Makefile
default:
g++ main.c -lpthread -o main.exe -lpthread
[tsecer@Harry pthreadexit]$ cat main.c
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

struct dest {
~dest(){printf("in %s\n",__FUNCTION__);}
}
;
void * worker(void * arg)
{
dest mylocal;當線程被pthread_kill的時候,註意這個局部變量的析構函數是否會被執行
printf("willing sleep \n");
sleep(1000);
printf("after sleep 1000\n");註意這個打印是否能夠打印出來
}
int main()
{
pthread_t thread;
pthread_create(&thread,NULL,worker,NULL);
sleep(2);
printf("killing worker\n");
pthread_cancel(thread);
sleep(2);
}
[tsecer@Harry pthreadexit]$ make
g++ main.c -lpthread -o main.exe -lpthread
[tsecer@Harry pthreadexit]$ ./main.exe
willing sleep
killing worker
in ~dest
[tsecer@Harry pthreadexit]$
三、結果
可以看到,當線程被殺死的時候,它依然頑強的執行了worker函數中局部變量 dest mylocal的析構函數(並且只執行了析構函數,緊鄰著sleep之後的print結構並沒有打印出來)。
從效果上看,它是保證程序完整性的重要基礎,事實上,對於C++代碼,這個語言特征的保證也是實現pthread_cleanup_push/pthread_cleanup_pop的C++實現基礎。
從編譯器實現上看,編譯器代碼增加了大量的eh_frame內容,其中使用到了DWARFS結構中的CIE及FDE等信息,這些信息是調試器進行堆棧回溯、函數局部變量顯示、棧幀寄存器顯示的基礎。這個結構比較復雜,如果展開可以展開很多內容。我也是大致看了個基本原理,很多東西不能自由展開,這裏就不再深入了。
大家知道這個C++語言特征,並且知道它的實現基礎是基於DWARFS格式就可以了。事實上,我們從代碼中看不到任何cleanup信息,所以如果有同學有時間有興趣了解它的實現基礎的話,可以向這個方向關註一下。

pthread_exit/pthread_kill之後局部對象之析構