0

I’m trying to make sense out of a few details obtained from the core file with respect to boost::optional type variable.

Variable:

boost::optional<Cacher> cacher_;

Frame #5 from the core:

(gdb) p this->cacher_
$1 = boost::optional

The line being executed in this frame is:

cacher_ = boost::none;

As a result, a few frames leading upto to the crash, point to boost library code:

#1  0x000000000152f96c in destroy_impl (this=0x32557590) at /opt/include/boost/optional/optional.hpp:479
#2  destroy (this=0x32557590) at /opt/include/boost/optional/optional.hpp:439
#3  assign (this=0x32557590) at /opt/include/boost/optional/optional.hpp:313
#4  operator= (none_=NULL, this=0x32557590) at /opt/include/boost/optional/optional.hpp:615

Frame #0 is where the destructor of Cacher is called, and the crash is because the memory held by the object has already been freed.

My question:

  1. Does boost::optional indicate that the memory held by cacher_ is valid?
  2. As a result of assigning boost::none to cacher_, would the object be destroyed?

Apologies if the details to diagnose the problem are insufficient. I’ll try to provide additional details based on the responses.

Thanks!

Maddy
  • 1,319
  • 3
  • 22
  • 37

1 Answers1

1

Yes, boost::optional keeps track of whether it holds a valid object. This can be checked by using operator bool() or is_initialized().

If you assign boost::none (or call .reset()) it will properly destroy the object it holds, if any.

The same holds true for std::optional (except for boost::none assignment, to the best of my knowledge).

krzaq
  • 16,240
  • 4
  • 46
  • 61
  • `(gdb) frame 3 #3 assign (this=0x32557590) at /opt/ include/boost/optional/optional.hpp:313 313 void assign ( none_t ) { destroy(); } (gdb) p *this $9 = { = {}, m_initialized = false, m_storage = {dummy_ = { data = “………………………………….", aligner_ = {}}}}` Does `m_initialized = false` indicate that the object is not valid? – Maddy Oct 13 '16 at 06:02
  • I don't think *valid* is a correct term. The optional is empty, there's no object stored in it. Kind of like empty `unique_ptr` (optional is very much like a smart pointer, but we use it for clarity). – krzaq Oct 13 '16 at 06:03
  • Ok. In the present case, what are we trying to destroy when there's no object? In any case, is it correct to assign `boost::none` without checking for whether `cacher_` is initialized or not? – Maddy Oct 13 '16 at 06:06
  • If there is no object nothing is supposed to be destroyed. It's safe to assign `boost::none` to such an optional but it should leave it in identical state (like assigning `nullptr` to already empty `unique_ptr`) – krzaq Oct 13 '16 at 06:07
  • Isn't the destructor called on an object? What am I missing in the present case? – Maddy Oct 13 '16 at 06:14
  • I'm not sure, to be honest. It's possible that your program was broken before, i.e. by stack smashing, and that's why you're seeing garbage. In a correct situation, optional won't call a destructor on non-object, – krzaq Oct 13 '16 at 06:23