From 29c53289a9e6bb34a098ea87d923968e3ac6d75d Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 7 Feb 2017 19:07:29 +0100 Subject: [PATCH] bench: Fix initialization order in registration The initialization order of global data structures in different implementation units is undefined. Making use of this is essentially gambling on what the linker does, the so-called [Static initialization order fiasco](https://isocpp.org/wiki/faq/ctors#static-init-order). In this case it apparently worked on Linux but failed on OpenBSD and FreeBSD. To create it on first use, make the registration structure local to a function. Fixes #8910. --- src/bench/bench.cpp | 16 ++++++++-------- src/bench/bench.h | 3 ++- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/bench/bench.cpp b/src/bench/bench.cpp index 1bd9d06b8..3c9df4f71 100644 --- a/src/bench/bench.cpp +++ b/src/bench/bench.cpp @@ -9,7 +9,10 @@ #include #include -std::map benchmark::BenchRunner::benchmarks; +benchmark::BenchRunner::BenchmarkMap &benchmark::BenchRunner::benchmarks() { + static std::map benchmarks_map; + return benchmarks_map; +} static double gettimedouble(void) { struct timeval tv; @@ -19,7 +22,7 @@ static double gettimedouble(void) { benchmark::BenchRunner::BenchRunner(std::string name, benchmark::BenchFunction func) { - benchmarks.insert(std::make_pair(name, func)); + benchmarks().insert(std::make_pair(name, func)); } void @@ -29,12 +32,9 @@ benchmark::BenchRunner::RunAll(double elapsedTimeForOne) std::cout << "#Benchmark" << "," << "count" << "," << "min" << "," << "max" << "," << "average" << "," << "min_cycles" << "," << "max_cycles" << "," << "average_cycles" << "\n"; - for (std::map::iterator it = benchmarks.begin(); - it != benchmarks.end(); ++it) { - - State state(it->first, elapsedTimeForOne); - benchmark::BenchFunction& func = it->second; - func(state); + for (const auto &p: benchmarks()) { + State state(p.first, elapsedTimeForOne); + p.second(state); } perf_fini(); } diff --git a/src/bench/bench.h b/src/bench/bench.h index 80dad6a8e..0e7605c72 100644 --- a/src/bench/bench.h +++ b/src/bench/bench.h @@ -63,7 +63,8 @@ namespace benchmark { class BenchRunner { - static std::map benchmarks; + typedef std::map BenchmarkMap; + static BenchmarkMap &benchmarks(); public: BenchRunner(std::string name, BenchFunction func);