Reputation: 718
I am aware of the question regarding combining AddressSanitizer and ThreadSanitizer. I am asking about this from the theoretical computer science point of view, prompted by an earlier discussion.
Consider the following buggy C++ program:
#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;
}
When compiled with GCC 14.2.0 or Clang 20 using -fsanitize=address
, the program will terminate instantly with a heap-use-after-free
error, because a()
is using a stale copy of a pointer.
When compiled without special options and run with valgrind ./a.out
, on my system the program would run for nearly 4 minutes before reporting the first Invalid read of size 1
. This I assume is because Valgrind is emulating multiple threads by preemptive scheduling in a single thread, and therefore you would need some luck to get a context switch between a()
and b()
at the right moment for the error to be reproduced.
Similarly, when the program is compiled with GCC or Clang using -fsanitize=thread
, it seems to keep running without any problem.
My question: Has there been any recent academic research that would improve upon the ThreadSanitizer algorithm in this respect?
Upvotes: -5
Views: 133
Reputation: 6936
Valgrind memcheck, DRD and Helgrind all detect errors in this code.
For DRD I recommend using --tool=drd --fair-sched=yes --check-stack-var=yes
.
For Helgrind I recommend using --tool=helgrind --fair-sched=yes
.
And for memcheck just --fair-sched=yes
.
Without fair scheduling it takes a bit longer to trigger the errors in my tests, sometimes 10 seconds whilst fair scheduling is generally within a few seconds.
Fair scheduling is only available on Linux. Porting it to FreeBSD is on my todo list.
Only one build required, and I only used GCC.
Upvotes: 2