关于全局变量致函数不可重入及本地拷贝恢复方案的疑问
关于全局变量拷贝恢复与函数可重入性的疑问
我理解全局变量更新会导致函数不可重入,这一点合理。但我不明白为何通过创建本地拷贝并恢复的方式可以解决该问题。
以下是示例代码:
int global_n = 10; void foo() { int local_n = global_n; global_n *= 10; if (global_n < 100) { printf("double digits\n"); } else { printf("not double digits\n"); } printf("%d\n", global_n); global_n = local_n; }
假设第一次执行foo()到第4行时,global_n变为100,此时被另一次foo()的调用中断,第二次执行第4行后global_n变为1000。如此一来该函数仍然不可重入,我的这个判断是否正确?
参考资料:GNU libc表述——若要在处理程序中调用修改特定内存对象的函数,可通过保存和恢复该对象来确保安全。我将其中的“内存”替换为了“全局变量”。
你的判断完全正确
这段代码的设计并没有让foo()变成可重入函数,原因很明确:
- 虽然函数末尾把全局变量恢复成了初始值,但在函数执行的中间阶段(第4行到第11行之间),
global_n的状态已经被修改。如果此时发生中断(比如信号处理程序触发了另一次foo()调用),第二次调用会基于被修改后的global_n值继续操作,直接破坏第一次调用的执行逻辑。 - 你假设的场景完全成立:第一次调用到第4行时
global_n变为100,被中断后第二次调用把它改成1000,等回到第一次调用时,后续的判断(第5行)会基于1000而不是预期的100执行,输出结果完全偏离第一次调用的预期,这正是不可重入的典型表现。
关于GNU libc表述的正确理解
GNU libc提到的“保存和恢复内存对象”,针对的是信号处理程序中调用非可重入函数的特定场景:如果信号处理程序需要修改某个全局变量,先保存它的原值,处理完成后恢复,这样可以避免信号处理程序对主程序中该变量的使用造成永久破坏。但这并不意味着被调用的函数本身变成了可重入的——它只是保证了全局变量最终会回到初始状态,避免留下副作用,但无法解决执行过程中并发访问导致的逻辑错乱。
如果要让foo()真正可重入,最根本的办法是彻底避免依赖全局变量,改为用局部变量传递状态;如果必须使用全局变量,就得用线程安全的同步机制(比如互斥锁)来保护对它的访问,但互斥锁本身可能带来死锁等新问题。
内容的提问来源于stack exchange,提问作者my_question
相关产品推荐
相关产品推荐

