From 4b422073f41c66ebd6ac26e9499f62914fe9bc0f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Radovan=20=C4=8Cerven=C3=BD?= <radovan.cerveny@gmail.com>
Date: Wed, 10 Feb 2016 16:26:01 +0100
Subject: [PATCH] fixed sneaky segfault, added safeguards to prevent segfaults

---
 .../src/measurements/CounterDataFrame.cpp     | 16 +++++++++----
 .../src/measurements/MeasurementEngine.cpp    | 10 ++++++++
 .../src/measurements/MeasurementEngine.hpp    |  3 +++
 .../src/measurements/MeasurementNew.cpp       |  2 ++
 .../src/measurements/MeasurementResults.cpp   |  3 +++
 .../src/measurements/MeasurementResults.hpp   |  1 +
 .../src/measurements/measurements.cpp         | 23 +++++++++++++------
 .../measurements/MeasurementsTest.cpp         |  4 ++++
 .../test-src/measurements/MeasurementsTest.h  |  2 ++
 9 files changed, 52 insertions(+), 12 deletions(-)

diff --git a/alib2measure/src/measurements/CounterDataFrame.cpp b/alib2measure/src/measurements/CounterDataFrame.cpp
index 4a07c9f85a..bc58f63a3a 100644
--- a/alib2measure/src/measurements/CounterDataFrame.cpp
+++ b/alib2measure/src/measurements/CounterDataFrame.cpp
@@ -14,9 +14,7 @@ void CounterDataFrame::init ( unsigned frame_idx, measurements::stealth_vector <
 		current_frame.counter.counters = parent_frame.counter.counters;
 }
 
-void CounterDataFrame::update ( unsigned frame_idx, measurements::stealth_vector < MeasurementFrame > & frames ) {
-	MeasurementFrame & current_frame = frames[frame_idx];
-	MeasurementFrame & parent_frame	 = frames[current_frame.parent_idx];
+void CounterDataFrame::update ( unsigned, measurements::stealth_vector < MeasurementFrame > & ) {
 }
 
 void CounterDataFrame::hint ( unsigned frame_idx, measurements::stealth_vector < MeasurementFrame > & frames, CounterHint hint ) {
@@ -62,7 +60,8 @@ void CounterDataFrame::xml_tokens ( std::deque < sax::Token > & tokens, unsigned
 	tokens.emplace_back ( "CounterData", sax::Token::TokenType::START_ELEMENT );
 
 	tokens.emplace_back ( "Counters", sax::Token::TokenType::START_ELEMENT );
-	for ( const auto & elem : cdf.counters) {
+
+	for ( const auto & elem : cdf.counters ) {
 		tokens.emplace_back ( "Counter", sax::Token::TokenType::START_ELEMENT );
 		tokens.emplace_back ( "Name", sax::Token::TokenType::START_ELEMENT );
 		tokens.emplace_back ( measurements::to_string ( elem.first ), sax::Token::TokenType::CHARACTER );
@@ -72,10 +71,12 @@ void CounterDataFrame::xml_tokens ( std::deque < sax::Token > & tokens, unsigned
 		tokens.emplace_back ( "Value", sax::Token::TokenType::END_ELEMENT );
 		tokens.emplace_back ( "Counter", sax::Token::TokenType::END_ELEMENT );
 	}
+
 	tokens.emplace_back ( "Counters", sax::Token::TokenType::END_ELEMENT );
 
 	tokens.emplace_back ( "RealCounters", sax::Token::TokenType::START_ELEMENT );
-	for ( const auto & elem : cdf.real_counters) {
+
+	for ( const auto & elem : cdf.real_counters ) {
 		tokens.emplace_back ( "Counter", sax::Token::TokenType::START_ELEMENT );
 		tokens.emplace_back ( "Name", sax::Token::TokenType::START_ELEMENT );
 		tokens.emplace_back ( measurements::to_string ( elem.first ), sax::Token::TokenType::CHARACTER );
@@ -85,6 +86,7 @@ void CounterDataFrame::xml_tokens ( std::deque < sax::Token > & tokens, unsigned
 		tokens.emplace_back ( "Value", sax::Token::TokenType::END_ELEMENT );
 		tokens.emplace_back ( "Counter", sax::Token::TokenType::END_ELEMENT );
 	}
+
 	tokens.emplace_back ( "RealCounters", sax::Token::TokenType::END_ELEMENT );
 
 	tokens.emplace_back ( "CounterData", sax::Token::TokenType::END_ELEMENT );
@@ -93,17 +95,21 @@ void CounterDataFrame::xml_tokens ( std::deque < sax::Token > & tokens, unsigned
 std::ostream & operator <<( std::ostream & os, const CounterDataFrame & cdf ) {
 
 	os << "(";
+
 	for ( auto it = cdf.counters.begin ( ); it != cdf.counters.end ( ); ++it ) {
 		os << it->first << " : " << it->second;
 
 		if ( it != cdf.counters.end ( ) ) os << ", ";
 	}
+
 	os << "), (";
+
 	for ( auto it = cdf.real_counters.begin ( ); it != cdf.real_counters.end ( ); ++it ) {
 		os << it->first << " : " << it->second;
 
 		if ( it != cdf.real_counters.end ( ) ) os << ", ";
 	}
+
 	os << ")";
 
 	return os;
diff --git a/alib2measure/src/measurements/MeasurementEngine.cpp b/alib2measure/src/measurements/MeasurementEngine.cpp
index c340917d55..b25fe87903 100644
--- a/alib2measure/src/measurements/MeasurementEngine.cpp
+++ b/alib2measure/src/measurements/MeasurementEngine.cpp
@@ -7,11 +7,18 @@
 namespace measurements {
 
 MeasurementEngine MeasurementEngine::INSTANCE;
+bool MeasurementEngine::NOT_DESTROYED;
 
 MeasurementEngine::MeasurementEngine ( ) {
+	MeasurementEngine::NOT_DESTROYED = true;
+
 	reset_measurements ( );
 }
 
+MeasurementEngine::~MeasurementEngine ( ) {
+	MeasurementEngine::NOT_DESTROYED = false;
+}
+
 void MeasurementEngine::push_measurement_frame ( measurements::stealth_string frame_name, measurements::Type frame_type ) {
 	unsigned parent_idx = frame_idx_stack.back ( );
 
@@ -31,6 +38,9 @@ void MeasurementEngine::push_measurement_frame ( measurements::stealth_string fr
 void MeasurementEngine::pop_measurement_frame ( ) {
 	unsigned current_idx = frame_idx_stack.back ( );
 
+	if ( frames[current_idx].type == measurements::Type::ROOT )
+		throw std::logic_error ( "no measurement started" );
+
 	frame_idx_stack.pop_back ( );
 
 	TimeDataFrame::update ( current_idx, frames );
diff --git a/alib2measure/src/measurements/MeasurementEngine.hpp b/alib2measure/src/measurements/MeasurementEngine.hpp
index b56641db67..f7211a8dd2 100644
--- a/alib2measure/src/measurements/MeasurementEngine.hpp
+++ b/alib2measure/src/measurements/MeasurementEngine.hpp
@@ -26,7 +26,10 @@ public:
 	template < typename Hint >
 	void hint ( Hint );
 
+	~MeasurementEngine ( );
+
 	static MeasurementEngine INSTANCE;
+	static bool NOT_DESTROYED;
 };
 
 }
diff --git a/alib2measure/src/measurements/MeasurementNew.cpp b/alib2measure/src/measurements/MeasurementNew.cpp
index 8207ddd7b1..5872d205b9 100644
--- a/alib2measure/src/measurements/MeasurementNew.cpp
+++ b/alib2measure/src/measurements/MeasurementNew.cpp
@@ -38,6 +38,8 @@ void * operator new( std::size_t n, bool measure ) {
 }
 
 void operator delete( void * ptr, bool measure ) noexcept {
+	if ( ptr == nullptr ) return;
+
 	std::size_t * sptr = static_cast < std::size_t * > ( ptr );
 
 	sptr--;
diff --git a/alib2measure/src/measurements/MeasurementResults.cpp b/alib2measure/src/measurements/MeasurementResults.cpp
index dfd5c3ea0b..9193ed7a92 100644
--- a/alib2measure/src/measurements/MeasurementResults.cpp
+++ b/alib2measure/src/measurements/MeasurementResults.cpp
@@ -5,6 +5,9 @@
 
 namespace measurements {
 
+MeasurementResults::MeasurementResults ( ) {
+}
+
 MeasurementResults::MeasurementResults ( const measurements::stealth_vector < MeasurementFrame > & frames ) : frames ( frames ) {
 }
 
diff --git a/alib2measure/src/measurements/MeasurementResults.hpp b/alib2measure/src/measurements/MeasurementResults.hpp
index 56b6653426..2b8517fb47 100644
--- a/alib2measure/src/measurements/MeasurementResults.hpp
+++ b/alib2measure/src/measurements/MeasurementResults.hpp
@@ -23,6 +23,7 @@ struct MeasurementXalloc {
 struct MeasurementResults {
 	measurements::stealth_vector < MeasurementFrame > frames;
 
+	MeasurementResults ( );
 	MeasurementResults ( const measurements::stealth_vector < MeasurementFrame > & );
 
 	void print_as_list ( std::ostream & ) const;
diff --git a/alib2measure/src/measurements/measurements.cpp b/alib2measure/src/measurements/measurements.cpp
index 51f72f96d3..9dc09222f0 100644
--- a/alib2measure/src/measurements/measurements.cpp
+++ b/alib2measure/src/measurements/measurements.cpp
@@ -7,34 +7,43 @@
 namespace measurements {
 
 void start ( measurements::stealth_string name, measurements::Type type ) {
-	MeasurementEngine::INSTANCE.push_measurement_frame ( std::move ( name ), type );
+	if ( MeasurementEngine::NOT_DESTROYED )
+		MeasurementEngine::INSTANCE.push_measurement_frame ( std::move ( name ), type );
 }
 
 void end ( ) {
-	MeasurementEngine::INSTANCE.pop_measurement_frame ( );
+	if ( MeasurementEngine::NOT_DESTROYED )
+		MeasurementEngine::INSTANCE.pop_measurement_frame ( );
 }
 
 void reset ( ) {
-	MeasurementEngine::INSTANCE.reset_measurements ( );
+	if ( MeasurementEngine::NOT_DESTROYED )
+		MeasurementEngine::INSTANCE.reset_measurements ( );
 }
 
 MeasurementResults results ( ) {
-	return MeasurementEngine::INSTANCE.get_results ( );
+	if ( MeasurementEngine::NOT_DESTROYED )
+		return MeasurementEngine::INSTANCE.get_results ( );
+	else
+		return MeasurementResults ( );
 }
 
 template < typename Hint >
 void hint ( Hint hint ) {
-	MeasurementEngine::INSTANCE.hint ( std::move ( hint ) );
+	if ( MeasurementEngine::NOT_DESTROYED )
+		MeasurementEngine::INSTANCE.hint ( std::move ( hint ) );
 }
 
 template < >
 void hint ( MemoryHint hint ) {
-	MeasurementEngine::INSTANCE.hint ( std::move ( hint ) );
+	if ( MeasurementEngine::NOT_DESTROYED )
+		MeasurementEngine::INSTANCE.hint ( std::move ( hint ) );
 }
 
 template < >
 void hint ( CounterHint hint ) {
-	MeasurementEngine::INSTANCE.hint ( std::move ( hint ) );
+	if ( MeasurementEngine::NOT_DESTROYED )
+		MeasurementEngine::INSTANCE.hint ( std::move ( hint ) );
 }
 
 }
diff --git a/alib2measure/test-src/measurements/MeasurementsTest.cpp b/alib2measure/test-src/measurements/MeasurementsTest.cpp
index 56d4a5a5a2..c043485c55 100644
--- a/alib2measure/test-src/measurements/MeasurementsTest.cpp
+++ b/alib2measure/test-src/measurements/MeasurementsTest.cpp
@@ -14,6 +14,10 @@ void MeasurementsTest::setUp ( ) {
 void MeasurementsTest::tearDown ( ) {
 }
 
+void MeasurementsTest::testConstructMeasurements ( ) {
+
+}
+
 void MeasurementsTest::testTimeMeasurements ( ) {
 	measurements::start ( "global", measurements::Type::OVERALL );
 	measurements::start ( "init", measurements::Type::INIT );
diff --git a/alib2measure/test-src/measurements/MeasurementsTest.h b/alib2measure/test-src/measurements/MeasurementsTest.h
index 1e53cd854e..4afc116c16 100644
--- a/alib2measure/test-src/measurements/MeasurementsTest.h
+++ b/alib2measure/test-src/measurements/MeasurementsTest.h
@@ -5,6 +5,7 @@
 
 class MeasurementsTest : public CppUnit::TestFixture {
   CPPUNIT_TEST_SUITE ( MeasurementsTest );
+  CPPUNIT_TEST ( testConstructMeasurements );
   CPPUNIT_TEST ( testTimeMeasurements );
   CPPUNIT_TEST ( testMemoryMeasurements );
   CPPUNIT_TEST ( testCounterMeasurements );
@@ -14,6 +15,7 @@ public:
   void setUp ( );
   void tearDown ( );
 
+  void testConstructMeasurements ( );
   void testTimeMeasurements ( );
   void testMemoryMeasurements ( );
   void testCounterMeasurements ( );
-- 
GitLab