Why does realloc() fail in this program with message *** glibc detected *** ./main.out: realloc(): invalid next size: [address(not null)] *** The result of the program is
0 Realloc BEGIN Realloc SIZE 4 ADDR 0 Realloc END Emplace BEGIN Emplace END ! 4 Emplace BEGIN Emplace END ! 4 Emplace BEGIN Emplace END ! 4 Emplace BEGIN Emplace END ! 4 Realloc BEGIN Realloc SIZE 10 ADDR 0x1123240
#include <iostream>
#include <cstdlib>
#include <new>
template<class T, class... Args>
class FastFunc;
template<class T, class... Args>
class FastFunc<T(Args...)>{
public:
template<class F>
FastFunc(F&& f) :
fobj_(new F(static_cast<F&&>(f))),
caller_(static_cast<Caller>([](void* f, Args&&... args) -> void {
(*reinterpret_cast<F*>(f))(static_cast<Args&&>(args)...);
})),
deleter_(static_cast<Deleter>([](void* f) -> void {
delete reinterpret_cast<F*>(f);
}))
{ }
~FastFunc()
{
deleter_(fobj_);
}
T operator()(Args&&... args) const
{
return caller_(fobj_, static_cast<Args&&>(args)...);
}
private:
typedef T(*Caller)(void*, Args&&...);
typedef void(*Deleter)(void*);
void* fobj_;
Caller caller_;
Deleter deleter_;
};
template<class T>
class Lazy {
public:
Lazy(T&& val) noexcept :
val_(static_cast<T&&>(val)),
chain_(nullptr),
cap_(0u),
size_(0u)
{ }
~Lazy()
{
void(get());
free(chain_);
}
template<class F>
void chain(F&& f)
{
if(size_ + 1 > cap_) {
std::cout << "Realloc BEGIN" << std::endl;
cap_ = (cap_ * 16) / 10 + 4;
std::cout << "Realloc SIZE " << cap_ << " ADDR " << chain_ << std::endl;
Chain* new_mem = reinterpret_cast<Chain*>(realloc(chain_, cap_));
if(new_mem != nullptr) {
chain_ = new_mem;
} else {
throw std::bad_alloc();
}
std::cout << "Realloc END" << std::endl;
}
std::cout << "Emplace BEGIN" << std::endl;
new (&chain_[size_++]) Chain(static_cast<F&&>(f));
std::cout << "Emplace END" << std::endl;
std::cout << '!' << std::endl;
}
T& get()
{
const Chain* const end = &chain_[size_];
const Chain* it = chain_;
while(it != end) {
(*it)(val_);
it->~Chain();
++it;
}
size_ = 0u;
return val_;
}
template<class F>
Lazy<T>& operator+=(F&& f)
{
chain(static_cast<F&&>(f));
return *this;
}
T& operator*()
{
return get();
}
public:
typedef FastFunc<void(T&)> Chain;
T val_;
Chain* chain_;
size_t cap_;
size_t size_;
};
int main()
{
Lazy<int> li (10);
for(int i = 0; i < 5; ++i) {
std::cout << li.cap_ << std::endl;
li.chain([](int& x) { x = x * x * x; });
}
std::cout << *li << std::endl;
}
Aucun commentaire:
Enregistrer un commentaire