Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Who is responsible for deleting the facet?

Tags:

c++

c++11

locale

I have a function that uses the Boost.DateTime library for generating the current GMT/UTC date and time string (live example).

std::string get_curr_date() {     auto date = boost::date_time::second_clock<boost::posix_time::ptime>::universal_time();      boost::posix_time::time_facet* facet = new boost::posix_time::time_facet("%a, %d %b %Y %H:%M:%S GMT");      std::ostringstream os;     os.imbue(std::locale(os.getloc(), facet));     os << date;      return os.str(); } 

This is mostly based on Boost.DateTime's example:

//example to customize output to be "LongWeekday LongMonthname day, year" //                                  "%A %b %d, %Y" date d(2005,Jun,25); date_facet* facet(new date_facet("%A %B %d, %Y")); std::cout.imbue(std::locale(std::cout.getloc(), facet)); std::cout << d << std::endl; // "Saturday June 25, 2005" 

My code worked nicely, but now I'm feeling uneasy because of these particular lines containing new:

  • boost::posix_time::time_facet* facet = new boost::posix_time::time_facet("%a, %d %b %Y %H:%M:%S GMT");

  • date_facet* facet(new date_facet("%A %B %d, %Y"));

As you can see, there is no delete in Boost.DateTime's so I somehow presumed that it is imperative for me to delete the date_facet. I used std::unique_ptr to wrap the newed time_facet object.

std::unique_ptr<boost::posix_time::time_facet> facet(new boost::posix_time::time_facet("%a, %d %b %Y %H:%M:%S GMT")); 

However, I am getting segfault errors, as you can see in here. I have also tried manually deleteing the newed pointer, and am still getting the same errors (sorry, can't reproduce error in Coliru).

The time_facet pointer is passed as an argument when constructing an std::locale object, so I'm confused who's the one responsible for deleteing the facet.

So here is the core of my question:

  • Am I required to delete the time_facet or is the std::locale object responsible for deleteing it?

Please note that boost::posix_time::time_facet is derived from boost::date_time::date_facet which is, in turn, derived from std::locale::facet. This question might generalized to std::locale::facet, though my problem is specific to time_facet.

Here are some docs on std::locale's constructors:

  • MSDN
  • cppreference.com
like image 241
Mark Garcia Avatar asked Jul 22 '13 03:07

Mark Garcia


1 Answers

Am I required to delete the time_facet or is the std::locale object responsible for deleteing the it?

You're not required to delete the time_facet so long as time_facet derives from std::locale::facet, which it should. The std::locale::facet is a base class that all facets should derive from that implement a form of reference counting. The standard says this:

§ 22.3.1.6

Once a facet reference is obtained from a locale object by calling use_facet<>, that reference remains usable, and the results from member functions of it may be cached and re-used, as long as some locale object refers to that facet.

Once all references of the facet are not being used, the destructor of std::locale will manage and delete references to the facet if its ref count is 0.

This is all specified in §22.3.1.1.2 in the C++11 standard. Where it states:

The refs argument to the constructor is used for lifetime management.

— For refs == 0, the implementation performs delete static_cast<locale::facet*>(f) (where f is a pointer to the facet) when the last locale object containing the facet is destroyed; for refs == 1, the implementation never destroys the facet.

like image 164
Rapptz Avatar answered Nov 05 '22 15:11

Rapptz