util: plug Regex memory leak

Previously, RegexMatcher::m_backrefManager and RegexBackrefManager::m_backrefs
own each other via shared_ptrs, causing a memory leak.
RegexBackrefManager::m_backrefs is now changed to weak_ptr.

refs #3673

Change-Id: I882a83ee1f29754721d9b3b9997b3bbc465df989
diff --git a/src/util/regex/regex-backref-manager.hpp b/src/util/regex/regex-backref-manager.hpp
index ceb1337..be0f3dd 100644
--- a/src/util/regex/regex-backref-manager.hpp
+++ b/src/util/regex/regex-backref-manager.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2013-2014 Regents of the University of California.
+ * Copyright (c) 2013-2016 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -21,8 +21,8 @@
  * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
  */
 
-#ifndef NDN_UTIL_REGEX_BACKREF_MANAGER_HPP
-#define NDN_UTIL_REGEX_BACKREF_MANAGER_HPP
+#ifndef NDN_UTIL_REGEX_REGEX_BACKREF_MANAGER_HPP
+#define NDN_UTIL_REGEX_REGEX_BACKREF_MANAGER_HPP
 
 #include "../../common.hpp"
 
@@ -35,13 +35,6 @@
 class RegexBackrefManager
 {
 public:
-  RegexBackrefManager()
-  {
-  }
-
-  virtual
-  ~RegexBackrefManager();
-
   size_t
   pushRef(const shared_ptr<RegexMatcher>& matcher);
 
@@ -49,22 +42,16 @@
   popRef();
 
   size_t
-  size();
+  size() const;
 
-  const shared_ptr<RegexMatcher>&
-  getBackref(size_t backrefNo);
+  shared_ptr<RegexMatcher>
+  getBackref(size_t i) const;
 
 private:
-  std::vector<shared_ptr<RegexMatcher> > m_backrefs;
+  std::vector<weak_ptr<RegexMatcher>> m_backrefs;
 };
 
 
-inline
-RegexBackrefManager::~RegexBackrefManager()
-{
-  m_backrefs.clear();
-}
-
 inline size_t
 RegexBackrefManager::pushRef(const shared_ptr<RegexMatcher>& matcher)
 {
@@ -81,18 +68,19 @@
 }
 
 inline size_t
-RegexBackrefManager::size()
+RegexBackrefManager::size() const
 {
   return m_backrefs.size();
 }
 
-inline const shared_ptr<RegexMatcher>&
-RegexBackrefManager::getBackref(size_t backrefNo)
+inline shared_ptr<RegexMatcher>
+RegexBackrefManager::getBackref(size_t i) const
 {
-  return m_backrefs[backrefNo];
+  auto backref = m_backrefs[i].lock();
+  BOOST_ASSERT(backref != nullptr);
+  return backref;
 }
 
-
 } // namespace ndn
 
-#endif // NDN_UTIL_REGEX_BACKREF_MANAGER_HPP
+#endif // NDN_UTIL_REGEX_REGEX_BACKREF_MANAGER_HPP
diff --git a/src/util/regex/regex-top-matcher.hpp b/src/util/regex/regex-top-matcher.hpp
index 465f8f0..777a4de 100644
--- a/src/util/regex/regex-top-matcher.hpp
+++ b/src/util/regex/regex-top-matcher.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2013-2014 Regents of the University of California.
+ * Copyright (c) 2013-2016 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -64,7 +64,7 @@
   static std::string
   convertSpecialChar(const std::string& str);
 
-private:
+NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
   const std::string m_expand;
   shared_ptr<RegexPatternListMatcher> m_primaryMatcher;
   shared_ptr<RegexPatternListMatcher> m_secondaryMatcher;
diff --git a/tests/unit-tests/util/regex.t.cpp b/tests/unit-tests/util/regex.t.cpp
index fc46c23..ea27473 100644
--- a/tests/unit-tests/util/regex.t.cpp
+++ b/tests/unit-tests/util/regex.t.cpp
@@ -439,6 +439,23 @@
   BOOST_CHECK_EQUAL(cm->expand(), Name("/ndn/edu/ucla/yingdi/mac/"));
 }
 
+BOOST_AUTO_TEST_CASE(RegexBackrefManagerMemoryLeak)
+{
+  auto re = make_unique<Regex>("^(<>)$");
+
+  weak_ptr<RegexPatternListMatcher> m1(re->m_primaryMatcher);
+  weak_ptr<RegexPatternListMatcher> m2(re->m_secondaryMatcher);
+  weak_ptr<RegexBackrefManager> b1(re->m_primaryBackrefManager);
+  weak_ptr<RegexBackrefManager> b2(re->m_secondaryBackrefManager);
+
+  re.reset();
+
+  BOOST_CHECK_EQUAL(m1.use_count(), 0);
+  BOOST_CHECK_EQUAL(m2.use_count(), 0);
+  BOOST_CHECK_EQUAL(b1.use_count(), 0);
+  BOOST_CHECK_EQUAL(b2.use_count(), 0);
+}
+
 BOOST_AUTO_TEST_SUITE_END() // TestRegex
 BOOST_AUTO_TEST_SUITE_END() // Util