什么会导致程序中的不确定输出?

发布于 2024-07-24 16:15:54 字数 372 浏览 6 评论 0原文

我的多进程程序有一个错误。 该程序接收输入并立即产生输出,不涉及网络,并且没有任何时间参考。 这个错误的原因很难追踪,因为它只是有时发生。

如果我不断运行它,它会产生正确和不正确的输出,没有明显的顺序或模式。

什么会导致这种不确定的行为? 有没有可以提供帮助的工具? 可能存在未初始化的变量。 我如何找到那些?

编辑:问题已解决,感谢任何提出建议的人 竞争条件。 我没有想到这一点主要是因为我确信我的设计可以防止这种情况发生。 问题是我使用了“wait”而不是“waitpid”,因此有时,当某个进程足够幸运地在我预期的进程之前完成时,正确的顺序就会变得疯狂。

I have a bug in a multi-processes program. The program receives input and instantly produces output, no network involved, and it doesn't have any time references.
What makes the cause of this bug hard to track down is that it only happens sometimes.

If I constantly run it, it produces both correct and incorrect output, with no discernible order or pattern.

What can cause such non-deterministic behavior? Are there tools out there that can help? There is a possibility that there are uninitialized variables in play. How do I find those?

EDIT: Problem solved, thanks for anyone who suggested
Race Condition.
I didn't thought of it mainly because I was sure that my design prevents this. The problem was that I've used 'wait' instead of 'waitpid', thus sometimes, when some process was lucky enough to finish before the one I was expecting, the correct order of things went wild.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

递刀给你 2024-07-31 16:15:54

你说这是一个“多进程”程序 - 你能更具体一些吗? 这很可能是您处理多个进程的竞争条件。

如果您能告诉我们更多有关流程如何交互的信息,我们也许能够提出一些可能性。 请注意,虽然 Artem 关于使用调试器的建议本身很好,但您需要注意,引入调试器很可能完全改变这种情况 - 特别是当涉及竞争条件时。 就我个人而言,我非常喜欢记录日志,但即使这样也可以巧妙地改变时间。

You say it's a "multi-processes" program - could you be more specific? It may very well be a race condition in how you're handling the multiple processes.

If you could tell us more about how the processes interact, we might be able to come up with some possibilities. Note that although Artem's suggestion of using a debugger is fine in and of itself, you need to be aware that introducing a debugger may very well change the situation completely - particularly when it comes to race conditions. Personally I'm a fan of logging a lot, but even that can change the timing subtly.

一江春梦 2024-07-31 16:15:54

调度员!

基本上,当您有多个进程时,它们可以按照它们想要的任何奇怪的顺序运行。 如果这些进程共享它们正在读取和写入的资源(无论是文件、内存还是某种 IO 设备),操作将会以各种奇怪的顺序交错。 举一个简单的例子,假设您有两个线程(它们是线程,因此它们共享内存)并且它们都试图增加全局变量 x。

y = x + 1;
x = y

现在运行这些进程,但以这种方式交错代码

假设x = 1

P1:

y = x + 1

所以现在在P1中,对于本地变量y并且在堆栈上,y = 2。 然后调度程序介入并启动 P2

P2:

y = x + 1
x = y

进入此过程时 x 仍然是 1,因此已将 1 添加到其中,现在 x = 2

然后 P1 完成

P1:

x = y

并且 x 仍然是 2! 我们将 x 增加了两次,但只得到了一次。 因为我们不知道这将如何发生,所以它被称为非确定性行为。

好消息是,您偶然发现了系统编程中最难的问题之一,也是许多函数式语言人员的主要战斗口号。

The scheduler!

Basically, when you have multiple processes, they can run in any bizarre order they want. If those processes are sharing a resource that they are both reading and writing from (whether it be a file or memory or an IO device of some sort), ops are going to get interleaved in all sorts of weird orders. As a simple example, suppose you have two threads (they're threads so they share memory) and they're both trying to increment a global variable, x.

y = x + 1;
x = y

Now run those processes, but interleave the code in this way

Assume x = 1

P1:

y = x + 1

So now in P1, for variable y which is local and on the stack, y = 2. Then the scheduler comes in and starts P2

P2:

y = x + 1
x = y

x was still 1 coming into this, so 1 has been added to it and now x = 2

Then P1 finishes

P1:

x = y

and x is still 2! We incremented x twice but only got that once. And because we don't know how this is going to happen, it's referred to as non-deterministic behavior.

The good news is, you've stumbled upon one of the hardest problems in Systems programming as well as the primary battle cry of many of the functional language folks.

霞映澄塘 2024-07-31 16:15:54

您很可能正在查看竞争条件,即不可预测的因此难以重现和调试不正确同步的线程或进程之间的交互。

这种情况下的非确定性源于进程/线程和内存访问调度。 这是不可预测的,因为它受到大量外部因素的影响,包括网络流量和用户输入,这些因素不断导致中断并导致每次运行程序时线程中的实际执行顺序不同。

You're most likely looking at a race condition, i.e. an unpredictable and therefore hard to reproduce and debug interaction between improperly synchronized threads or processes.

The non-determinism in this case stems from process/thread and memory access scheduling. This is unpredictable because it is influenced by a large number of external factors, including network traffic and user input which constantly cause interrupts and lead to different actual sequences of execution in the program's threads each time it's run.

甜点 2024-07-31 16:15:54

可能是很多事情,内存泄漏,关键部分访问,未关闭的资源,未关闭的连接等等。只有一种工具可以帮助你 - DEBUGGER,或者尝试检查你的算法并找到错误,或者如果你成功指出有问题的部分,您可以在此处粘贴一个片段,我们会尽力帮助您。

It could be a lot of things, memory leaks, critical sections access, unclosed resources, unclosed connection and etc. There is only one tool which can help you - DEBUGGER, or try examine your algorithm and find bug, or if you succeeded to point the problematic part, you can paste here a snippet and we will try to help you.

小梨窩很甜 2024-07-31 16:15:54

从基础开始...确保所有变量都有默认值,并且所有动态内存在使用之前都已清零(即使用 calloc 而不是 malloc)。 应该有一个编译器选项来标记这一点(除非您使用一些不起眼的编译器)。

如果这是 C++(我知道它应该是一个“c”论坛),有时对象创建和初始化会落后于变量赋值,这可能会让您感到困扰。 例如,如果您有一个由多个线程同时使用的作用域(如在单例或全局变量中),这可能会导致问题:

if (!foo)
Foo tmp = new Foo();

如果有多个线程访问上述内容,第一个线程会找到 foo = null 并开始对象创建和赋值,然后产生。 另一个线程进来并发现 foo != null 因此跳过该部分并开始使用 foo。

Start with the basics... make sure that all your variables have a default value and that all dynamic memory is zeroed out before you use it (i.e. use calloc rather than malloc). There should be a compiler option to flag this (unless you're using some obscure compiler).

If this is c++ (I know it's supposed to be a 'c' forum), there are times were object creation and initialization lags behind variable assignment that can bite you. For example if you have a scope that is used concurrently by multiple threads (as in a singleton or a global var) this can cause issues:

if (!foo)
Foo tmp = new Foo();

If you have multiple threads access the above, the first thread finds foo = null and starts the object creation and assignment and then yields. Another thread comes in and finds foo != null so skips the section and starts to use foo.

可爱暴击 2024-07-31 16:15:54

我们需要查看有关代码的具体信息,以便能够给出更准确的答案,但为了简洁起见,当您有一个在多个进程或多线程之间进行协调的程序时,线程执行时间的变量可能会增加不确定性你的申请。 从本质上讲,操作系统所做的调度可能会导致进程和线程无序执行。 根据您的环境和代码,操作系统所做的调度可能会导致截然不同的结果。 您可以在google上搜索更多有关多线程乱序执行的信息; 这是一个很大的话题。

We'd need to see specifics about your code to be able to give a more accurate answer, but to be concise, when you have a program that coordinates between multiple processes or multiple threads, the variable of when the threads execute can add indeterminacy to your application. Essentially, the scheduling that the OS does can cause processes and threads to execute out-of-order. Depending on your environment and code, the scheduling that the OS does can cause wildly different results. You can search on google for more information about out-of-order execution with multithreading for more information; it's a large topic.

孤城病女 2024-07-31 16:15:54

“多进程”是指多线程吗? 如果我们有两个线程执行此例程

i = 1;
while(true)
{
    printf(i++);
    if(i > 4) i = 1;
}

通常我们期望输出类似于

112233441122334411223344

但实际上我们会看到类似的结果

11232344112233441231423

这是因为每个线程都会以不同的速率使用 CPU。 (日程安排背后有很多复杂的事情,我太弱了,无法告诉你其背后的技术内容。)可以说,从普通人的角度来看,日程安排是相当随机的。

这是其他评论中提到的竞争条件的示例。

By "multi-process" do you mean multi-threaded? If we had two threads that do this routine

i = 1;
while(true)
{
    printf(i++);
    if(i > 4) i = 1;
}

Normally we'd expect the output to be something like

112233441122334411223344

But actually we'd be seeing something like

11232344112233441231423

This is because each thread would get to use the CPU at different rates. (There's a whole lot of complicated behind the scheduling schedule, and I'm too weak to tell you the technical stuffs behind it.) Suffice to say, the scheduling from the average person's point of view is pretty random.

This is an example of race condition mentioned in other comments.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文