函数的可重入性

示例:

// 可重入函数
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,所以就得到了下面的结果。





  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值