You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

函数调用未排序修改全局变量是否引发UB?加mutex能否解决?

未指定顺序函数调用与未定义行为的问题解答

一、原始代码是否存在未定义行为(UB)

先看原始代码:

int counter = 0;

int mul_func(int x) {
  counter *= x;
  x = counter;
  return x;
}

int add_func(int x) {
  counter += x;
  x = counter;
  return x;
}

int main(void) {
  int sum = add_func(3) + mul_func(2);
}

这段代码不存在未定义行为,仅存在未指定行为:

  • C标准规定,表达式中函数调用的执行顺序是未指定的,编译器可选择先执行add_func(3)再执行mul_func(2),或者反过来。
  • 单线程下两个函数的执行是原子的,不会出现交错修改全局变量counter的情况,最终只会产生两种确定的合法结果:
    1. 先执行add_func:counter变为3,再执行mul_func将counter乘2得到6,sum = 3 + 6 = 9
    2. 先执行mul_func:counter乘以2仍为0,再执行add_func将counter加3得到3,sum = 0 + 3 = 3
      未指定行为仅导致结果不确定,但程序行为完全符合标准约束,不属于未定义行为。

二、添加互斥锁后的效果

先修正代码中的两处错误:pthread_mutex_d应为pthread_mutex_t,pthread_mutex_init需传入属性参数(可传NULL使用默认属性),修正后的代码如下:

#include <pthread.h>

int counter = 0;
pthread_mutex_t mtx;

int mul_func(int x) {
  pthread_mutex_lock(&mtx);
  counter *= x;
  x = counter;
  pthread_mutex_unlock(&mtx);
  return x;
}

int add_func(int x) {
  pthread_mutex_lock(&mtx);
  counter += x;
  x = counter;
  pthread_mutex_unlock(&mtx);
  return x;
}

int main(void) {
  pthread_mutex_init(&mtx, NULL);
  int sum = add_func(3) + mul_func(2);
  pthread_mutex_destroy(&mtx);
}

在单线程场景下,添加互斥锁不会解决任何问题(也不会引入问题):

  • 互斥锁的作用是解决多线程下的数据竞争,但这段代码是单线程执行,本来就不存在数据竞争。
  • 函数调用的顺序依然是未指定的,编译器仍可选择先执行任意一个函数,最终结果依然是之前的两种可能之一。
  • 这段代码不存在未定义行为,结果的不确定性依然是未指定行为导致的,而非UB。

三、无数据竞争的“未排序”是否会引发UB

明确结论:不会。

  • 未指定顺序的函数调用(单线程下),只要没有数据竞争(单线程天然不存在数据竞争),且没有违反C标准的其他规则(比如对同一个对象的无同步读写),那么程序的行为就是标准允许的——只是结果取决于编译器选择的执行顺序,但每种可能的结果都是合法的,不属于未定义行为。
  • 未定义行为是指标准完全放弃对程序行为的约束(比如可能崩溃、输出无意义结果等),而未指定行为只是结果不确定,但程序的每一种可能行为都在标准的约束范围内。

内容的提问来源于stack exchange,提问作者D.J. Elkind

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 06:24:54