【发布时间】:2015-03-21 01:07:45
【问题描述】:
根据我的经验,我在使用 printf(或任何其他标准输出日志记录)进行调试时遇到了一些奇怪的行为。
行为 1:
一个常见的场景是在多线程应用程序中使用 printf 以找出某些错误发生的原因,并使用 printf 突然“修复”错误(积极调用的 ofc printfs,导致巨大的输出)。
在这种情况下,我认为 printf 会增加一些延迟,因此可能会有一些低优先级的线程无法获得 CPU,因此我开始朝那个方向寻找。
我关注 printf 修复奇迹的另一个方向是同步,因为我推测对 printf 的调用虽然是多线程的,但在系统后面是同步的,因此使用 printf 的不同线程通过等待彼此来在它们之间同步完成写入 I/O 缓冲区。
Q1:我对第一种情况的两个假设是否正确?
Q2:当这种情况发生时,我应该考虑其他方向吗?
行为 2:
这种情况很少发生,但一旦碰到它,即使是高级开发人员也会质疑自己,我非常感谢对此的解释。
它是这样的:
- 代码不起作用...(清理、编译、运行)
- 代码仍然不起作用,所以你添加一个 printf 来查看原因(清理、编译、运行)
- 代码开始正常工作......您删除了之前添加的 printf(清理、编译、运行)
- 代码现在可以正常工作了!!!!!!!!!! (挠头,难以置信地盯着看)。
在实践中,我使用这种方法的次数超过了一次,这种修复 CPU 的方法可能不止一次地钉住错误:Android "cpu may be pegged" bug。
它实际上工作得很好,以至于它成为了一个已知的“修复”(如果它从第一次尝试就不起作用,你只需重复这个过程直到它消失)。
请注意,代码已被正确清理,它绝不是与旧编译对象链接的问题。
最流行的猜测之一是编译代码不同的事实,原因不明(编译器是否根据某个文件的行有一些随机性,包括空格?)。
Q3:这种行为可能是什么原因(我也愿意猜测)?尽管代码相同,编译器可以生成不同的程序集吗?
请注意,我所说的项目非常大,有多个静态库,因此这些行为在小代码 sn-ps 上是不可复制的(尽管我听说场景 2 发生在单个文件上程序)。
【问题讨论】:
-
请一次只作为一个问题。 SO 意味着可搜索并将知识带给他人。
-
看起来您的代码有问题,原因是同步错误。您的代码可能会根据不可预测的系统行为运行/失败,这与 printf 无关。您将不得不检查共享变量、程序员在您的代码中所做的任何类型的休眠或时序假设。
-
@Jens Gustedt 我理解你只发布一个问题的意思,但我相信这个问题可以给社区带来的一般知识是“为什么有时你似乎用 printf 解决问题”。我给出了两种情况,可能行为 1 和行为 2 的原因不同,但是从开发人员的 POV 来看,他刚刚输入了 printf,然后魔术发生了。
标签: c++ c multithreading io