Why is the desctructor being invoked in this scenario? - c++

In the following code , I am not able to understand why the destructor of the class Buf is invoked twice. When debugging I can see that it is being invoked the first time when the running thread is leaving the function Test::produce. The second time is when leaving the main function which essentially is when destructing the class EventQueue, something I would expect.
However, I dont understand why when leaving the function Test::produce the destructor of Buf is invoked. Specifically, I create the class Buf as a r-value passing it to the EventQueue and move to its internal cache. In fact, this has created me the problem that I end up trying ti free the same pointer twice which throws an exception.
template<typename T>
class EventQueue{
public:
void offer(T&& t) {
m_queue.try_emplace(std::this_thread::get_id()).first->second.push(std::move(t));
};
std::unordered_map<std::thread::id, std::queue<T>> m_queue;
};
class Buf{
const uint8_t *m_data;
const size_t m_size;
public:
Buf(const uint8_t *data, size_t size) : m_data(data), m_size(size) { }
size_t size() const { return m_size; }
const uint8_t *data() const { return m_data; }
~Buf()
{
std::cout << "dtor called " << std::endl;
free((void *)m_data);
}
};
class Test{ and was not expecting
public:
Test(shared_ptr<EventQueue<Buf>> buf) : m_buf(buf)
{
std::thread t1 = std::thread([this] { this->produce(10); });
t1.detach();
};
void produce(int msg_size) {
m_buf->offer(Buf(new uint8_t[msg_size], 10));
}
std::shared_ptr<EventQueue<Buf>> m_buf;
};
int main()
{
auto event_queue = std::make_shared<EventQueue<Buf>>();
Test tt(event_queue);
return 0;
}

The destructor is called two times because you have two objects to destroy. First - the temporary you created as an argument for the offer function parameter:
void produce(int msg_size) {
m_buf->offer(Buf(new uint8_t[msg_size], 10));
}
Second - when you add this temporary to std::queue container, it makes a copy under the hood:
void offer(T&& t) {
m_queue.try_emplace(std::this_thread::get_id()).first->second.push(std::move(t));
};
Every temporary object created must always be destructed. However the problem is not about how many objects were destructed, but that you ignore the rules of zero, three and five here. I.e. if you create any of a destructor, a copy constructor or a copy-assignment operator, you are supposed to take care of all three. Another side effect is that the compiler will not generate the move constructor and move assignment operator for you when any of the big three are explicitly defined. Thus, when passing rvalue-reference to a Buf constructor, you actually ends up with a copy constructor.
However even if it was a default move constructor, it would not solve your problem, because resources represented with raw pointers which your class instance "owns" (and is supposed to delete at some point) are not quite compatible with the implicit move constructor, which merely does member-wise std::move:
For non-union class types (class and struct), the move constructor performs full member-wise move of the object's bases and non-static members, in their initialization order, using direct initialization with an xvalue argument.
For any built-in types (including raw pointers), it means that nothing actually happens and they are just copied.
Long story short: you have to nullify the source object's member raw pointer explicitly:
Buf(Buf&& other) noexcept : m_data{ std::exchange(other.m_data, nullptr) }, m_size{ other.m_size } {}
The better solution would be to not mess with rules of three/five and stick to rule of zero, by leveraging RAII idiom and letting automatic storage duration to handle the resources without explicitly allocating/releasing them:
class Buf{
const std::vector<std::uint8_t> m_data;
public:
Buf(std::vector<std::uint8_t> data) : m_data{ std::move(data) } { }
const std::vector<std::uint8_t>& data() const {
return m_data;
}
};

Related

If std::vector reallocates objects to new memory by using move constructor then why does it have to call the destructor on the original objects? [duplicate]

This question already has answers here:
why is the destructor call after the std::move necessary?
(2 answers)
Closed 8 months ago.
If the move constructor of your class is noexcept then std::vector will allocate new memory and then move construct your objects in the new memory. If it's not "noexcept" it will copy construct them. If it copy constructs them, then those objects still need to be destroyed before deallocating the old buffer. However why is it the case that if the object is moved it still calls the destructors on all the old objects. I don't see why this is necessary. Any destructor call on a moved-from object is not going to do anything, apart from some conditional checks. You could argue that the "object is technically not destroyed", and that's true, but since that memory is being deallocated, and the next time that memory is used the only defined way to access objects there is to construct them first, I don't see why this needs to be done:
struct Foo
{
void* buffer;
Foo() : buffer(new char[16]) {}
Foo(Foo&& other) { buffer = other.buffer; if (other.buffer != nullptr) other.buffer = nullptr; }
~Foo()
{
if (buffer != nullptr) delete buffer;
}
};
int main()
{
Foo foo;
Foo foo2 = std::move(foo);
foo.~Foo(); /* NO EFFECT */
/* BUT ASSUMING WE DIDN'T CALL THE CONSTRUCTOR, WE JUST CONSTRUCT OVER IT */
new (&foo) Foo{};
/* THEN THE OLD FOO CEASES TO EXIST EVEN IF THE DESTRUCTOR IS NEVER CALLED */
}
Here is a quick program showing that std::vector calls the destructors on the old moved-from objects:
#include <iostream>
struct Foo
{
Foo() {}
Foo(uint32 id) { }
Foo(const Foo& other)
{
std::cout << "Copy constructor called\n";
}
Foo(Foo&& other) noexcept
{
std::cout << "Move constructor called\n";
};
~Foo()
{
std::cout << "Destructor called\n";
}
};
int main()
{
Foo foo;
std::vector<Foo> v;
v.push_back(std::move(foo));
v.push_back(std::move(foo));
v.push_back(std::move(foo));
v.push_back(std::move(foo));
}
To end an object's lifetime, its destructor must be called.
Also, what happens when an object it moved is up to the implementation of the class. You have two objects and the move constructor is allowed to move resources around how it sees fit.
An example of a simple string class which, when moving, leaves the moved-from object in a valid state:
class string {
public:
string(const char* s) : m_len(std::strlen(s)), m_data(new char[m_len + 1]) {
std::copy_n(s, m_len + 1, m_data);
}
string(string&& rhs) :
m_len(std::exchange(rhs.m_len, 0)),
m_data(std::exchange(rhs.m_data, new char[1]{}))
{}
~string() {
delete[] m_data;
}
private:
size_t m_len;
char* m_data;
};
Without calling the destructor of the moved-from object, it would leak. An implementation like above is not uncommon. Just because an object has been move-from, it doesn't mean that it's void of resources to free.

How forbid to call member function for temporary object (C++)

I have the template class data_ptr which has the member operator * for access to the pointer to data:
operator T*() { return m_pPtr; }
Also inside the constructor of data_ptr its pointer is "pinned" in memory and in destructor is "unpinned".
I want to forbid using the operator* is this way:
data_ptr<T> GetSomeDataPtr { return data_ptr<T>(...); }
T *pRawPointerToData = *GetSomeDataPtr();
... because the function GetSomeDataPtr returns the temporary object data_ptr, and when the destructor gets called its data pointer becomes invalid, so we get a crash when accessing the pRawPointerToData.
So, the main idea is to use compiler to find such code. I am using Visual Studio 2015 Update 3.
Example:
template <class T> class data_ptr
{
public:
data_ptr(T val) : p(new T(val)) {}
~data_ptr() {delete p;}
operator T*() { return p; }
private:
T *p;
};
template <class T>
data_ptr<T> GetSomeDataPtr(T val)
{
return data_ptr<T>(val);
}
int main()
{
int &rawReferenceToData = *GetSomeDataPtr<int>(123);
rawReferenceToData = 456; // << invalid access to already deleted object!
return 0;
}
You can declare operator T* with an lvalue ref-qualifier, i.e.
operator T*() & { return p; }
so that this conversion can be called only for a lvalue of data_ptr, which means a temporary (rvalue) is forbidden to call this conversion.
There are also some defects with your design. Even if an object is not a temporary, it will be destroyed later at some time, and those T*s previously exposed do not know the destroy, which has potential danger of invalid access. As a result, it is the caller's responsibility to guarantee no invalid access, so you don't have to limit this call for temporary objects. As an example, std::string::c_str does not have such limitations.

Array initialization of objects without operator =, copy constructor or default constructor and run-time arguments

Disclaimer
I'm trying to allocate an array of objects that are neither copy constructible, assignable nor has a default constructor. The objects have arguments that are determined at run time. I know that you can solve this problem by having an array of pointers or cleverly using placement new but I'm more interested in if this is possible to do cleanly with C++11 (1y) magic. So please, this is purely of theoretical interest so avoid trying to solve "my problem" by offering a work around.
The code...
...So the question is: Is there a way to make the following work in C++11 or C++14:
class X{
public:
explicit X(int a){...}
X(const X&) = delete;
void operator = (const X&) = delete;
private:
...
};
class Y{
public:
Y(const std::vector<int>& args) {
x = new X[]{args};
}
~Y(){
delete [] x;
}
private:
X* x;
};
Criteria
Specifically I'm looking for a solution/construct that meets the following criteria:
X is not copy constructible.
X is not assignable.
X does not have a default no-argument constructor (construction has intended side-effects).
The arguments to X's constructor are not known until run time.
All instances of X must be laid out contiguously in memory.
X must be properly destructed when the array is deleted from it's base pointer (or if an intermediate class is used, when the intermediate object is destructed). This rules out array of pointers and naivë use of placement new.
Edit / Addendum
I forgot to mention that move constructor is not available. In the actual case at hand, X spawns a worker thread and is executing in the context of this of the initially constructed object, any attempt to use a move constructor will corrupt the state of the executing thread.
You can use std::vector and its emplace_back function if you make X at least movable.
class X{
public:
explicit X(int){}
X(X&&) = default;
X(const X&) = delete;
void operator = (const X&) = delete;
};
int main() {
std::vector<X> xs;
xs.emplace_back(0);
xs.emplace_back(1);
xs.emplace_back(2);
xs.emplace_back(3);
}
(If you declare a copy constructor, even if that declaration deletes it, the compiler will not automatically generate any special move member, so you need to explicitly request them)
This basically boils down to the "array with placement new" strategy, but all abstracted away into high-level notions.
If you cannot make use of a movable type, you have to implement a vector-like class that pre-allocates storage and never reallocates. There is nothing similar in the standard library.
You're going to have to keep track of the constructed elements by hand, but you can use allocator to help:
class Y{
public:
Y(const std::vector<int>& args):
alloc{},
n{args.size()},
x{alloc.allocate(n)}
{
auto end = x;
try {
for (auto arg: args)
alloc.construct(end++, arg);
} catch (...) {
while (end != x)
alloc.destroy(--end);
alloc.deallocate(x, n);
throw;
}
}
~Y() {
for (auto end = std::next(x, n); end != x; --end)
alloc.destroy(end);
alloc.deallocate(x, n);
}
private:
std::allocator<X> alloc;
const std::size_t n;
const X *x;
};
A class that is neither copyable nor movable, nor has a default constructor, cannot be held in a standard container (doesn't meet the requirements) or a variable-sized array allocation (which only allows argument specification for a fixed number of elements).
This means you need to allocate raw memory instead and use placement new to construct the objects. You can wrap this in a fixed-space vector class.
template <typename T>
class fixed_capacity_vector {
public:
using size_type = std::size_t;
fixed_capacity_vector(size_type capacity)
: data_(::operator new(capacity * sizeof(T)), size_(), capacity_(capacity)
{}
fixed_capacity_vector(const fixed_capacity_vector&) = delete;
fixed_capacity_vector(fixed_capacity_vector&&) = delete;
fixed_capacity_vector& operator =(const fixed_capacity_vector&) = delete;
fixed_capacity_vector& operator =(fixed_capacity_vector&&) = delete;
~fixed_capacity_vector() {
for (size_type i = 0; i < size_; ++i) data_[i].~T();
::operator delete(data_);
}
template <typename... Args>
T& emplace_back(Args&&... args) {
if (size_ == capacity_) throw out_of_range();
new (data_ + size_) T(std::forward<Args>(args)...);
++size_;
return data_[size_-1];
}
private:
T* data_;
size_type size_;
size_type capacity_;
};

Run-time polymorphic class with value semantics

I would like a class Value, which both has a run-time polymorphic behaviour, and a value semantics. For instance, I would like to be able to do things like:
// create polymorphic data
Value v1 = IntValue(42);
Value v2 = DoubleValue(12.3);
// copy-by-value semantics
Value v3 = v1;
v3.increments();
Value v4;
v4 = v2;
v4.increments();
// possibly put them in my favourite container
MyList<Value> l;
l << v1 << v2 << v3 << v4;
// print them: "Int(42) Double(12.0) Int(43) Double(13.0) "
for(int i=0; i<l.size(); i++) l[i].print();
Is it possible, and if yes, how?
Note: Using boost or C++11 smart pointers as here is not desired: they make the caller code verbose, use -> instead of ., and do not have copy constructors or assignment operators implementing a true value semantics. Also, this question doesn't target specifically containers.
polymorphic_value has been proposed for standardisation and has some of the semantics you require. You'll have to define your own operator << though.
A polymorphic_value<T> may hold a an object of a class publicly derived from T, and copying the polymorphic_value will copy the object of the derived type.
polymorphic_value<T> is implemented with type erasure and uses the compiler-generated copy-constructor of the derived objects to correctly copy objects stored as polymorphic_value<BaseType>.
Copy constructors and assignment operators are defined so that the objects are value-like. There is no need to use or define a custom clone method.
In brief:
template <class T>
struct control_block
{
virtual ~control_block() = default;
virtual T* ptr() = 0;
virtual std::unique_ptr<control_block> clone() const = 0;
};
template <class T>
class polymorphic_value {
std::unique_ptr<control_block<T>> cb_;
T* ptr_ = nullptr;
public:
polymorphic_value() = default;
polymorphic_value(const polymorphic_value& p) :
cb_(p.cb_->clone())
{
ptr_ = cb_->ptr();
}
T* operator->() { return ptr_; }
const T* operator->() const { return ptr_; }
T& operator*() { return *ptr_; }
const T& operator*() const { return *ptr_; }
// Some methods omitted/deferred.
};
Specializations of the control block allow other constructors to be defined.
Motivation and design is discussed here :
https://github.com/jbcoe/polymorphic_value/blob/master/talks/2017_1_25_cxx_london.md
and here
https://github.com/jbcoe/polymorphic_value/blob/master/draft.md
A full implementation with tests can be found here:
https://github.com/jbcoe/polymorphic_value
It's hard to know what you're trying to achieve here, but at first guess it seems that the (upcoming) Boost Type Erasure library might be suitable?
any<
mpl::vector<
copy_constructible<>,
typeid_<>,
incrementable<>,
ostreamable<>
>
> x(10);
++x;
std::cout << x << std::endl; // prints 11
(Example from docs).
Yes, it is possible, but of course there must be some hidden pointer, and the actual data must be stored on the heap. The reason is that the actual size of the data cannot be known at compile-time, and then can't be on the stack.
The idea is to store the actual implementation through a pointer of a polymorphic class ValueImpl, that provides any virtual method you need, like increments() or print(), and in addition a method clone(), so that your class Data is able to implement the value semantics:
class ValueImpl
{
public:
virtual ~ValueImpl() {};
virtual std::unique_ptr<ValueImpl> clone() const { return new ValueImpl(); }
virtual void increments() {}
virtual void print() const { std::cout << "VoidValue "; }
};
class Value
{
private:
ValueImpl * p_; // The underlying pointer
public:
// Default constructor, allocating a "void" value
Value() : p_(new ValueImpl) {}
// Construct a Value given an actual implementation:
// This allocates memory on the heap, hidden in clone()
// This memory is automatically deallocated by unique_ptr
Value(const ValueImpl & derived) : p_(derived.clone()) {}
// Destruct the data (unique_ptr automatically deallocates the memory)
~Value() {}
// Copy constructor and assignment operator:
// Implements a value semantics by allocating new memory
Value(const Value & other) : p_(other.p_->clone()) {}
Value & operator=(const Value & other)
{
if(&other != this)
{
p_ = std::move(other.p_->clone());
}
return *this;
}
// Custom "polymorphic" methods
void increments() { p_->increments(); }
void print() { p_->print(); }
};
The contained pointer is stored inside a C++11 std::unique_ptr<ValueImpl> to ensure the memory is released when destroyed or assigned a new value.
The derived implementations can finally be defined the following way:
class IntValue : public ValueImpl
{
public:
IntValue(int k) : k_(k) {}
std::unique_ptr<IntValue> clone() const
{
return std::unique_ptr<IntValue>(new IntValue(k_));
}
void increments() { k_++; }
void print() const { std::cout << "Int(" << k_ << ") "; }
private:
int k_;
};
class DoubleValue : public ValueImpl
{
public:
DoubleValue(double x) : x_(x) {}
std::unique_ptr<DoubleValue> clone() const
{
return std::unique_ptr<DoubleValue>(new DoubleValue(k_));
}
void increments() { x_ += 1.0; }
void print() const { std::cout << "Double(" << x_ << ") "; }
private:
int x_;
};
Which is enough to make the code snippet in the question works without any modification. This provides run-time polymorphism with value semantics, instead of the traditional run-time polymorphism with pointer semantics provided built-in by the C++ language. In fact, the concept of polymorphism (handling generic objects that behave differently according to their true "type") is independent from the concept of pointers (being able to share memory and optimize function calls by using the address of an object), and IMHO it is more for implementation details that polymorphism is only provided via pointers in C++. The code above is a work-around to take advantage of polymorphism when using pointers is not "philosophically required", and hence ease memory management.
Note: Thanks for CaptainObvlious for the contribution and his evolved code available here that I partially integrated. Not integrated are:
To ease the creation of derived implementations, you may want to create an intermediate templated class
You may prefer to use an abstract interface instead of my non-abstract base class

What are the use cases for having a function return by const value for non-builtin type?

Recently I have read that it makes sense when returning by value from a function to qualify the return type const for non-builtin types, e.g.:
const Result operation() {
//..do something..
return Result(..);
}
I am struggling to understand the benefits of this, once the object has been returned surely it's the callers choice to decide if the returned object should be const?
Basically, there's a slight language problem here.
std::string func() {
return "hai";
}
func().push_back('c'); // Perfectly valid, yet non-sensical
Returning const rvalues is an attempt to prevent such behaviour. However, in reality, it does way more harm than good, because now that rvalue references are here, you're just going to prevent move semantics, which sucks, and the above behaviour will probably be prevented by the judicious use of rvalue and lvalue *this overloading. Plus, you'd have to be a bit of a moron to do this anyway.
It is occasionally useful. See this example:
class I
{
public:
I(int i) : value(i) {}
void set(int i) { value = i; }
I operator+(const I& rhs) { return I(value + rhs.value); }
I& operator=(const I& rhs) { value = rhs.value; return *this; }
private:
int value;
};
int main()
{
I a(2), b(3);
(a + b) = 2; // ???
return 0;
}
Note that the value returned by operator+ would normally be considered a temporary. But it's clearly being modified. That's not exactly desired.
If you declare the return type of operator+ as const I, this will fail to compile.
There is no benefit when returning by value. It doesn't make sense.
The only difference is that it prevents people from using it as an lvalue:
class Foo
{
void bar();
};
const Foo foo();
int main()
{
foo().bar(); // Invalid
}
Last year I've discovered another surprising usecase while working on a two-way C++-to-JavaScript bindings.
It requires a combination of following conditions:
You have a copyable and movable class Base.
You have a non-copyable non-movable class Derived deriving from Base.
You really, really do not want an instance of Base inside Derived to be movable as well.
You, however, really want slicing to work for whatever reason.
All classes are actually templates and you want to use template type deduction, so you cannot really use Derived::operator const Base&() or similar tricks instead of public inheritance.
#include <cassert>
#include <iostream>
#include <string>
#include <utility>
// Simple class which can be copied and moved.
template<typename T>
struct Base {
std::string data;
};
template<typename T>
struct Derived : Base<T> {
// Complex class which derives from Base<T> so that type deduction works
// in function calls below. This class also wants to be non-copyable
// and non-movable, so we disable copy and move.
Derived() : Base<T>{"Hello World"} {}
~Derived() {
// As no move is permitted, `data` should be left untouched, right?
assert(this->data == "Hello World");
}
Derived(const Derived&) = delete;
Derived(Derived&&) = delete;
Derived& operator=(const Derived&) = delete;
Derived& operator=(Derived&&) = delete;
};
// assertion fails when the `const` below is commented, wow!
/*const*/ auto create_derived() { return Derived<int>{}; }
// Next two functions hold reference to Base<T>/Derived<T>, so there
// are definitely no copies or moves when they get `create_derived()`
// as a parameter. Temporary materializations only.
template<typename T>
void good_use_1(const Base<T> &) { std::cout << "good_use_1 runs" << std::endl; }
template<typename T>
void good_use_2(const Derived<T> &) { std::cout << "good_use_2 runs" << std::endl; }
// This function actually takes ownership of its argument. If the argument
// was a temporary Derived<T>(), move-slicing happens: Base<T>(Base<T>&&) is invoked,
// modifying Derived<T>::data.
template<typename T>
void oops_use(Base<T>) { std::cout << "bad_use runs" << std::endl; }
int main() {
good_use_1(create_derived());
good_use_2(create_derived());
oops_use(create_derived());
}
The fact that I did not specify the type argument for oops_use<> means that the compiler should be able to deduce it from argument's type, hence the requirement that Base<T> is actually a real base of Derived<T>.
An implicit conversion should happen when calling oops_use(Base<T>). For that, create_derived()'s result is materialized into a temporary Derived<T> value, which is then moved into oops_use's argument by Base<T>(Base<T>&&) move constructor. Hence, the materialized temporary is now moved-from, and the assertion fails.
We cannot delete that move constructor, because it will make Base<T> non-movable. And we cannot really prevent Base<T>&& from binding to Derived<T>&& (unless we explicitly delete Base<T>(Derived<T>&&), which should be done for all derived classes).
So, the only resolution without Base modification here is to make create_derived() return const Derived<T>, so that oops_use's argument's constructor cannot move from the materialized temporary.
I like this example because not only it compiles both with and without const without any undefined behaviour, it behaves differently with and without const, and the correct behavior actually happens with const only.