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 1bd9d06b803..3c9df4f713c 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 80dad6a8ef5..0e7605c7267 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);