有没有同时检查内存安全和数据竞争的算法?

问题描述 投票:0回答:1

我知道有关组合 AddressSanitizer 和 ThreadSanitizer 的问题。我是从理论计算机科学的角度来问这个问题的,是由之前的讨论引发的。

考虑以下有缺陷的 C++ 程序:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <thread>
#include <mutex>

static std::mutex m;
static char *buf;

static void a()
{
  for (;;) {
    char *b;
    {
      std::lock_guard<std::mutex> g{m};
      b = buf;
    }
    if (b)
      puts(b);
  }
}

static void b()
{
  for (;;) {
    {
      std::lock_guard<std::mutex> g{m};
      buf = strdup("foo");
    }

    {
      std::lock_guard<std::mutex> g{m};
      buf = static_cast<char*>(realloc(buf, 10000));
      strcpy(buf, "barbarbar");
    }

    {
      std::lock_guard<std::mutex> g{m};
      free(buf);
      buf = nullptr;
    }
  }
}

int main()
{
  auto thread_a = std::thread(a);
  auto thread_b = std::thread(b);
  thread_a.join();
  // unreachable
  thread_b.join();
  return 0;
}

当使用

-fsanitize=address
使用 GCC 14.2.0 或 Clang 20 进行编译时,程序将立即终止并出现
heap-use-after-free
错误,因为
a()
使用的是指针的过时副本。

当在没有特殊选项的情况下编译并使用

valgrind ./a.out
运行时,在我的系统上,程序将运行近 4 分钟,然后报告第一个
Invalid read of size 1
。我认为这是因为 Valgrind 通过在单个线程中抢占式调度来模拟多个线程,因此您需要一些运气才能在正确的时刻在
a()
b()
之间进行上下文切换,以便重现错误。

同样,当使用GCC或Clang使用

-fsanitize=thread
编译程序时,它似乎可以继续运行,没有任何问题。

我的问题:最近是否有任何学术研究可以在这方面改进ThreadSanitizer算法

c++ c multithreading valgrind address-sanitizer
1个回答
0
投票

Valgrind memecheck、DRD 和 Helgrind 都检测到此代码中的错误。

对于 DRD,我建议使用

--tool=drd --fair-sched=yes --check-stack-var=yes

对于 Helgrind,我建议使用

--tool=helgrind --fair-sched=yes

对于 memcheck 只是

--fair-sched=yes

如果没有公平调度,在我的测试中触发错误需要更长的时间,有时需要 10 秒,而公平调度通常在几秒钟内。

公平调度仅适用于 Linux。将其移植到 FreeBSD 已在我的待办事项清单上。

只需要一次构建,而且我只使用了 GCC。

© www.soinside.com 2019 - 2024. All rights reserved.