C 可能不确定的行为会导致调试和释放构建行为不同



这个问题有许多很好的答案,解释了为什么错误只能在发行版中表现出来。
发行版本中不存在的错误原因在调试模式中不存在
我对不确定的行为有一个更具体的问题。

如果程序在调试构建中似乎总是正确地工作,但是在发布构建中行为不同(但是,始终以相同的不正确方式行为),问题是否是由于不确定的行为引起的吗?

可以是由于不确定的行为吗?当然。由于行为不确定,它是总是吗?当然不是。

想象一下:

assert(scanf("%d", &n) == 1);

此行只需在发布模式下即可删除。这不是不确定的行为,但最肯定会使您的程序以不同的方式行事。

assert可能是这里明显的例子,但是想想这种更复杂的情况:

#ifndef NDEBUG
# define DBG(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
#else
# define DBG(fmt, ...) ((void)0)
#endif
int shared_var;
static inline void do_something_fast(void)
{
    DBG("doing something fastn");
    shared_var = something_fast();
}

并有线程1:

...
mutex_unlock();
local_var = shared_var;
...

和线程2:

...
mutex_lock();
do_something_fast();
...

现在,这个示例完全荒谬,但是在多线程环境中,这些示例很常见。在此示例中,这就是发生的事情:

  • 线程1:呼叫Mutex_unlock,唤醒线程2并去睡觉
  • 线程2:调用do_something_fast()
    • 发行版:fprintf被称为,导致线程2入睡
      • 现在线程1将shared_var的旧值复制到local_var
    • 在调试中:线程一个覆盖shared_var
      • 现在线程1将shared_var的新值复制到local_Var

您可以看到,在此示例中,阻止I/O强迫线程之间的某些行为,这本身仅在调试模式下才启用。这也意味着,在调试中工作的程序的行为可能与释放时不同。

最新更新