C++ 如何诊断奇怪的种族条件错误?

C++ 如何诊断奇怪的种族条件错误?,c++,race-condition,vxworks,C++,Race Condition,Vxworks,我们正在跟踪的缺陷发生在特定的基于VxWorks的嵌入式环境中(供应商将内容修改到未知的程度,并提供了VxWorks内容的抽象层)。我们有两个任务以不同的优先级运行,大约每100毫秒执行一次。优先级较高的任务只是将整数相加(这样它就可以执行任何操作),而优先级较低的任务创建一个字符串,如下所示: std::string text("Some text"); 请注意,这些任务之间没有任何共享状态。它们都只对自动局部变量进行操作 在每次运行中,每个任务都会这样做一百次,因此竞争条件发生的概率更高。

我们正在跟踪的缺陷发生在特定的基于VxWorks的嵌入式环境中(供应商将内容修改到未知的程度,并提供了VxWorks内容的抽象层)。我们有两个任务以不同的优先级运行,大约每100毫秒执行一次。优先级较高的任务只是将整数相加(这样它就可以执行任何操作),而优先级较低的任务创建一个字符串,如下所示:

std::string text("Some text");
请注意,这些任务之间没有任何共享状态。它们都只对自动局部变量进行操作

在每次运行中,每个任务都会这样做一百次,因此竞争条件发生的概率更高。应用程序可以正常运行几分钟,然后CPU负载从5%上升到100%,并保持不变。整个时间似乎由创建字符串的任务使用。到目前为止,我们还无法在不使用
std::string
的情况下再现该行为

我们正在使用GCC4.1.2并在VxWorks5.5上运行。该程序在奔腾III上运行


我已经尝试过分析那里发生的事情,但是我无法使用调试器输入任何
string
-方法,并且将print语句添加到basic string中似乎不起作用(这是的背景)。我怀疑里面有什么东西会破坏堆栈,导致电源循环。我的问题是,在旧的VxWorks版本中是否存在可以解释这一点的已知错误?如果没有,您是否有进一步的建议如何诊断?我可以得到反汇编和堆栈转储,但我在解释这两个方面都没有经验。有人可以吗?

如果我记得的话,vxWorks提供了线程特定的内存位置(或者可能只有一个位置)。此功能允许您指定一个内存位置,该位置将被任务开关自动隐藏,以便每当线程在其上写入时,该值将在任务开关之间保留。这有点像一个额外的寄存器保存/恢复

GCC使用这些线程特定的内存位置之一来跟踪异常堆栈。即使您不使用异常,也有一些情况(特别是
new
,例如
std::string
构造函数可能调用)隐式创建
try/catch
类环境来操作此堆栈。在一个更老的gcc版本中,我看到代码中出现了乱码,名义上没有使用任何异常处理


在这种情况下,解决方案是使用
-fno异常编译,以消除所有这些行为,然后问题就消失了。

如果我记得的话,vxWorks提供了特定于线程的内存位置(或者可能只有一个位置)。此功能允许您指定一个内存位置,该位置将被任务开关自动隐藏,以便每当线程在其上写入时,该值将在任务开关之间保留。这有点像一个额外的寄存器保存/恢复

GCC使用这些线程特定的内存位置之一来跟踪异常堆栈。即使您不使用异常,也有一些情况(特别是
new
,例如
std::string
构造函数可能调用)隐式创建
try/catch
类环境来操作此堆栈。在一个更老的gcc版本中,我看到代码中出现了乱码,名义上没有使用任何异常处理


在这种情况下,解决方案是使用
-fno异常进行编译,以消除所有的行为,然后问题就消失了。

每当我看到VxWorks系统中出现奇怪的、行为无法解释的竞态情况时,我的第一个想法总是“VX\u FP\u任务再次攻击!”您应该检查的第一件事是您的线程是否使用taskSpawn中的VX_FP_任务标志创建


文档中说“在没有VxYFPII任务选项的情况下执行一个任务时执行任何浮点操作是致命的,而且很难找到”现在,你可能会认为你根本不使用FP寄存器,但是C++使用了一些优化,MMX操作(比如你可以在你的加法中使用)。确实需要保留这些寄存器

每当我在一个VxWorks系统中看到一个奇怪的、行为无法解释的竞态条件时,我的第一个想法总是“VX\u FP\u任务再次攻击!”你应该检查的第一件事是你的线程是否是用taskSpawn中的VX\u FP\u任务标志创建的


文档中说“在没有VxYFPII任务选项的情况下执行一个任务时执行任何浮点操作是致命的,而且很难找到”现在,你可能会认为你根本不使用FP寄存器,但是C++使用了一些优化,MMX操作(比如你可以在你的加法中使用)。确实需要保留这些寄存器

使用
-fno异常编译没有帮助。我也无法通过手动创建
try/catch
环境并使用
new
delete
分配/释放内存来重现该错误。使用
-fno异常编译也没有帮助。我也无法通过手动创建
try/catch
环境并使用
new
delete
分配/释放内存来重现该错误。