代码之家  ›  专栏  ›  技术社区  ›  Razican

单元测试仅在ARM中失败

  •  0
  • Razican  · 技术社区  · 10 年前

    我正在为Raspberry Pi开发一个多线程程序,我注意到我们当前的代码在我的计算机和其他大学的计算机中运行得很好,但在ARM上运行时失败了。

    我们在项目中使用C++11,这是我们计算机中的输出:

    ............ 成功 测试运行完成。运行了12次测试。12例成功。

    但当我们尝试在ARM上运行它时,如您所见: https://travis-ci.org/OpenStratos/server/builds/49297710

    上面写着:

    .... 在过去10分钟内没有收到任何输出,这可能表明构建已停止或构建本身有问题。

    经过一些调试后,我明白问题出在这段代码上: https://github.com/OpenStratos/server/blob/feature/temperature/serial/Serial.cpp#L91

    this->open = false;
    while( ! this->stopped);
    

    还有另一个线程在做相反的事情:

    while(this->open)
    {
        // Do stuff
    }
    this->stopped = true;
    

    当我需要停止线程时,调用第一个代码,并使用双标志使线程能够更新当前对象,即使它正在停止。这两个变量的类型都是std::atomic_bool,但在 while ( ! this->stopped); 它不会检查它,但它假设 while (true); .

    是这样吗?如何解决?为什么它在x86_64处理器上的工作方式与在ARM上的不同?

    提前感谢。

    2 回复  |  直到 10 年前
        1
  •  1
  •   MSalters    10 年前

    核心担保由 std::atomic<T> 你总是可以阅读 价值不一定保证一致性。

    现在,在这种情况下,你依靠的是 .operator bool 相当于 .load(memory_order_seq_cst) operator=(x) 这是 .store(x, memory_order_seq_cst) 。这将为您提供顺序一致的内存顺序。

    你在ARM上观察到的顺序在我看来是顺序一致的 然而 看到 stopped == true 没问题,没有时间限制。编译器无法将内存操作与另一个内存操作交换,但可能会无限期地延迟它。

    主要问题是为什么这个线程应该停止。如果在该线程的循环体中完成了任何实际的、可观察到的工作,则该循环体不能相对于 stopped==true 检查

        2
  •  0
  •   Razican    10 年前

    最后,问题是我在Travis.ci中创建的环境工作不正常。在现实中,ARM硬件工作正常。