示例:
// 可重入函数
int double(int a){
return a*2;
}
// 不可重入函数
void foo(){
static int intarray[28];
static int index;
if(index > 19) return;
intarray[index] = 9;
index++;
}
对于函数中使用的某一个变量,若两次调用该函数时,这个变量都执行相同的结果,说明该函数是可重入的,否则是不可重入的。
从经验上来讲就是:如果函数中使用了全局变量或者静态变量,则该函数是不可重入的,否则是可重入的。
下面给一个例子来说明不可重入函数。
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
int g_v[10];//全局变量
int *h_v;//堆中的数据
void set(int val)
{
int a_v[10];
int i = 0;//注意到这里的i是局部变量
for(; i < 10; ++i)
{
a_v[i] = val;
g_v[i] = val;
h_v[i] = val;
sleep(1);//给一个发送信号的时间
}
printf("g_v:");
for(i = 0; i < 10; ++i)
{
if(i != 0)
printf(",%d", g_v[i]);
else
printf("%d", g_v[i]);
}
printf("\n");
printf("h_v:");
for(i = 0; i < 10; ++i)
{
if(i != 0)
printf(",%d", h_v[i]);
else
printf("%d", h_v[i]);
}
printf("\n");
printf("a_v:");
for(i = 0; i < 10; ++i)
{
if(i != 0)
printf(",%d", a_v[i]);
else
printf("%d", a_v[i]);
}
printf("\n");
}
void sig_handler(int signo)
{
if(signo == SIGTSTP)
{
printf("SIGTSTP occured\n");
set(20);// 在信号处理函数中又调用set
printf("end SIGTSTP\n");
}
}
int main(void)
{
if(signal(SIGTSTP, sig_handler) == SIG_ERR)
perror("signal sigtstp error");
h_v = (int*)calloc(10, sizeof(int));
printf("begin running main\n");
set(10);
printf("end running main\n");
return 0;
}
上述代码中定义了两个全局变量g_v和h_v,还在set函数中定义了一个局部变量a_v,在set函数中给这三个数组赋值。
如果过程中没有发生信号,则代码执行结果如下:
如果在执行set给三个变量赋值的过程中产生了一个SIGTSTP信号,则程序转到信号处理函数中,并第二次执行set函数。
由于a_v属于栈中数据,所以每次执行都会重新分配一个栈空间。而g_v和h_v分别属于数据段空间和堆空间,所以在整个程序执行过程中只开辟一段内存空间。根据执行结果可以分析出,第一次执行set时,当i=1执行完,即第二次赋值完成后产生了一个SIGTSTP信号。于是执行第一次set函数中断,稍后接着第二次执行set函数,所以第一次输出全部为20。这时转到第一次中断处继续执行,因为第一次执行到i=1处中断,所以从i=2接着继续赋值。第一个栈中的a_v前两个已经赋值为10,所以这里接着赋值10,最后全部为10。而g_v和h_v现在全部为20,但是此时要从中断处即i=2处继续赋值,所以前两个为20保持不变,后面的依然赋值为10,所以就得到了下面的结果。