C 可能不确定的行为会导致调试和释放构建行为不同
C++ Can Undefined Behavior cause Debug and Release Builds to behave differently?
这个问题有许多很好的答案,解释了为什么错误只能在发行版中表现出来。
发行版本中不存在的错误原因在调试模式中不存在
我对不确定的行为有一个更具体的问题。
如果程序在调试构建中似乎总是正确地工作,但是在发布构建中行为不同(但是,始终以相同的不正确方式行为),问题是否是由于不确定的行为引起的吗?
可以是由于不确定的行为吗?当然。由于行为不确定,它是总是吗?当然不是。
想象一下:
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
- 现在线程1将
- 在调试中:线程一个覆盖
shared_var
- 现在线程1将
shared_var
的新值复制到local_Var
- 现在线程1将
- 发行版:fprintf被称为,导致线程2入睡
您可以看到,在此示例中,阻止I/O强迫线程之间的某些行为,这本身仅在调试模式下才启用。这也意味着,在调试中工作的程序的行为可能与释放时不同。
相关文章:
- 当回溯以零开始时,如何调试崩溃
- 释放错误后堆使用
- G锁定铸造到基础上会释放模拟行为
- 在将变量声明为引用时,堆在释放后使用
- 在linux上调试巨大的C++项目
- 在调用FreeLibrary后,释放动态链接到具有相同版本的CRT堆的DLL的内存
- 为什么使用__LINE_的代码在发布模式下在MSVC下编译,而不是在调试模式下
- MS Visual C 释放和调试构建之间的不同行为的可能原因
- ActiveX OCX可以在释放模式内置时注册,但不能在调试模式下注册
- 断言在释放中抛出,但不进行调试 - 一定是编译器错误
- 如何在程序崩溃后释放managedsharedmemory:在调试过程中使用哪些有效的技术
- 使用 Valgrind 调试释放后使用
- C 可能不确定的行为会导致调试和释放构建行为不同
- 调试对释放内存的非法访问
- 调试断言失败!错误的内存释放
- 在调试模式下释放静态数组时出错
- 进行内存释放时出现调试错误
- 在std: vector中擦除,调试,释放
- 串口工作在调试,但不释放c++代码块窗口
- 调试DLL与释放EXE