Example of memory leak in c++ (by use of exceptions) - c++

In C++ How to program there is a paragraph that say:
A common programming practice is to allocate dynamic memory, assign the address of
that memory to a pointer, use the pointer to manipulate the memory and deallocate the
memory with delete when the memory is no longer needed. If an exception occurs after
successful memory allocation but before the delete statement executes, a memory leak
could occur. The C++ standard provides class template unique_ptr in header to
deal with this situation.
Any on could introduce me a real example that exception occur and memory will leak like this post?

A bit more subtle example.
Take an naive implementation of a class that holds two dynamically allocated arrays:
struct Foo {
private:
int* first;
int* second;
public:
Foo()
: first(new int[10000])
, second(new int[10000])
{ }
void Bar() { throw 42; }
~Foo()
{
delete [] first;
delete [] second;
}
};
int main()
{
Foo f;
/* more code */
}
Now, if we get an exception because we call method Bar somewhere, everything's fine - the stack unwinding guarantess that f's destructor gets called.
But if we get a bad_alloc when initializing second, we leak the memory that first points to.

class MyClass
{
public:
char* buffer;
MyClass(bool throwException)
{
buffer = new char[1024];
if(throwException)
throw std::runtime_error("MyClass::MyClass() failed");
}
~MyClass()
{
delete[] buffer;
}
};
int main()
{
// Memory leak, if an exception is thrown before a delete
MyClass* ptr = new MyClass(false);
throw std::runtime_error("<any error>");
delete ptr;
}
int main()
{
// Memory leak due to a missing call to MyClass()::~MyClass()
// in case MyClass()::MyClass() throws an exception.
MyClass instance = MyClass(true);
}
See also: C++ : handle resources if constructors may throw exceptions (Reference to FAQ 17.4]

void func()
{
char *p = new char[10];
some_function_which_may_throw(p);
delete [] p;
}
If the call to some_function_which_may_throw(p) throws an exception we leak the memory pointed to by p.

Simple example
try {
int* pValue = new int();
if (someCondition) {
throw 42;
}
delete pValue;
} catch (int&) {
}

To have a less contrived example, I recently found this potential leak in my code when allocating nodes with a given allocator object.
std::unique_ptr<node,alloc_aware> allocate_new_node(allocator& al, const value_type^ v) {
char* buffer = al.allocate(sizeof(node)); //allocate memory
return std::unique_ptr<node>(al.construct(buffer, v),{al})); //construct
}
It's less obvious how to fix this because of the buffer, but with help I got it:
struct only_deallocate {
allocator* a;
size_type s;
only_deallocate(allocator& alloc, size_type size):a(&alloc), s(size) {}
template<class T> void operator()(T* ptr) {a->deallocate(ptr, s);}
operator alloc_aware() const {return alloc_aware(*a, s);}
};
std::unique_ptr<node,alloc_aware> allocate_new_node(allocator& al, const value_type& v) {
std::unique_ptr<node, only_deallocate> buf(alloc.allocate(sizeof(node)),{alloc, sizeof(node)});//allocate memory
alloc.construct(buf.get(), value);
return std::unique_ptr<node,alloc_aware>(std::move(buf));
}
Compiling Code here

Related

How to use shared_ptr to manage an object placed with placement new?

A fairly common thing I need to do is allot an object and some memory it'd like, in a strictly contagious region of memory together:
class Thing{
static_assert(alignof(Thing) == alignof(uint32), "party's over");
public:
~Thing(){
//// if only, but this would result in the equivalent of `free(danglingPtr)` being called
//// as the second stage of shared_ptr calling `delete this->get()`, which can't be skipped I believe?
// delete [] (char*)this;
}
static Thing * create(uint32 count) {
uint32 size = sizeof(Thing) + sizeof(uint32) * count; // no alignment concerns
char * data = new char[size];
return new (data)Thing(count);
}
static void destroy(Thing *& p) {
delete [] (char*)p;
p = NULL;
}
uint32 & operator[](uint32 index) {
assert(index < m_count);
return ((uint32*)((char*)(this + sizeof(Thing))))[index];
}
private:
Thing(uint32 count) : m_count(count) {};
uint32 m_count;
};
int main(){
{
auto p = shared_ptr<Thing>(Thing::create(1));
// how can I tell p how to kill the Thing?
}
return 0;
}
In Thing::Create() this is done with placement new into a section of memory.
I'd also like to have a shared pointer manage it in this case, using auto p = shared_ptr<Thing>(Thing::create(1)). But If it calls the equivalent of delete p.get() when the ref count empties, that'd be undefined as it mismatches the type and, more importantly, mismatches plural new with singular delete. I need it to delete in a special way.
Is there a way to easily set that up without defining an outside function? Perhaps by having the shared pointer call Thing::destroy() when the ref count empties? I know that shared pointer can accept a "deleter" as a template argument, but I'm unsure how to use it, or if it's even the proper way to address this?
std::shared_ptr accepts a deleter function as a second parameter, so you can use that to define how the managed object will be destroyed.
Here's a simplified example:
class Thing
{
public:
~Thing()
{
std::cout << "~Thing\n";
}
static std::shared_ptr<Thing> create() {
char * data = new char[sizeof(Thing)];
Thing* thing = new (data) Thing{};
return std::shared_ptr<Thing>{thing, &Thing::destroy};
}
static void destroy(Thing* p) {
p->~Thing();
delete [] (char*)p;
}
};
int main()
{
auto p = Thing::create();
}
Live Demo

Is there any limitation in friend function to alloc memory to array member?

I am searching for a long time on net. But no use. Please help or try to give some ideas:
I found a reproductive error in template class when I tried to alloc more space for a dynamic array member managed by a pointer with a friend function. If I turn to another member function, or just in the Push(), to finish this process, error vanished.
Independent from private/public accessibility, Error cover all field of array member accession, once I tried to read or delete element in it, error happend.
No clear tips were given by GCC compiler. Error didn't affect basic types, like int.
Binding friend & Unbinding friend both suffer from this error
Is there anything wrong in my code, or there is some limitation I didn't know in using memory function?
Every opinion, link and anwser is appreciated.
PS: To make posted code more clearly, I simplify some unimportant code. But to provide enough imformation, it still looks so long, feel sorry to the
reading difficulty.
PS2:Guarantee can be made that code simplified is correct.
Error occurs both in Debug mode(x64 and x86),Visual Studio 2017
and cmake 3.13.4-GCC 7.2.0 toolchain debugging with gdb in VScode.
//Bizcard.hpp
class Bizcard
{
private:
char *name;
char *phone;
public:
Bizcard();
Bizcard(const char* n,const char* phone);//constructor
Bizcard(const Bizcard &b);//copy constructor
Bizcard& operator=(const Bizcard& b);//assignment operator
~Bizcard();
};
//Bizcard.cpp
#include"Bizcard.hpp"
#include<string.h>
#include<iostream>
Bizcard::Bizcard()
{
name = nullptr;
phone = nullptr;
}
Bizcard::Bizcard(const char* n ,const char* p)
{
//simplified...
}
Bizcard::Bizcard(const Bizcard &b)
{
//simplified...
}
Bizcard& Bizcard::operator=(const Bizcard& b)
{
if(this==&b)
return *this;
delete[] this->name;//Error would occur here if using
//friend func to expand array capacity
delete[] this->phone;
if(b.name==nullptr)
{
name = nullptr;
phone = nullptr;
return *this;
}
int nlen = strlen(b.name);
int plen = strlen(b.phone);
this->name = new char[nlen+1];
strcpy_s(name, nlen + 1, b.name);
this->phone = new char[plen+1];
strcpy_s(phone, plen + 1, b.phone);
return *this;
}
Bizcard::~Bizcard()
{
delete[] name;
delete[] phone;
}
//BagTemplate.hpp
#include<stdlib.h>
#include<algorithm>
#include<iostream>
#include"Bizcard.hpp"
template<typename Type>
void ChangeSize1D_binding(Type* array, int old_capacity, int new_capacity)
{
if(new_capacity<old_capacity)
throw "Paragram Error! New capacity must greater than the old one.";
Type* temp_array =new Type[new_capacity];
std::copy(array,array+old_capacity,temp_array);
delete[] array;
array = temp_array;//Point array to the dest of temp_array
}
template<typename T>
class Bag
{
public:
Bag(int bagCapability =3);
~Bag();
void Push(const T&);
void ChangeSize1D_self(int old_capacity, int new_capacity);
private:
T *array;
int capacity;
int top;
friend void ChangeSize1D_binding<T>(T* array, int old_capacity, int new_capacity);
template<typename Type>
friend void ChangeSize1D_unbind(Type* array, int old_capacity, int new_capacity);
};
template<typename T>
Bag<T>::Bag(int bagCapacity):capacity(bagCapacity)
{
if(capacity<1) throw "Capacity must be >0";
array = new T[capacity];
top = -1;
}
template<typename T>
Bag<T>::~Bag()
{
delete[] array;
}
template<typename T>
void Bag<T>::ChangeSize1D_self(int old_capacity,int new_capacity)
{
if(new_capacity<old_capacity)
throw "Paragram Error! New capacity must greater than the old one.";
T* temp_array =new T[new_capacity];
std::copy(array,array+old_capacity,temp_array);
delete[] array;
array = temp_array;
}
template<typename Type>
void ChangeSize1D_unbind(Type* array, int old_capacity, int new_capacity)
{
if(new_capacity<old_capacity)
throw "Paragram Error! New capacity must greater than the old one.";
Type* temp_array =new Type[new_capacity];
std::copy(array,array+old_capacity,temp_array);
delete[] array;
array = temp_array;
}
template<typename T>
void Bag<T>::Push(const T& x)
{
if(capacity ==top+1)
{
//this->ChangeSize1D_self(capacity,2*capacity);
ChangeSize1D_unbind(array,capacity, 2*capacity);
//ChangeSize1D_binding(array,capacity, 2*capacity);
/*T* temp_array = new T[2 * capacity];
std::copy(array,array+capacity,temp_array);
delete[] array;
array = temp_array;*/
capacity*=2;
}
array[++top]=x;
}
//main.cpp
int main()
{
Bag<int> IntBag;
IntBag.Push(1);
IntBag.Push(1);
IntBag.Push(1);
IntBag.Push(1);
Bag<Bizcard> BizcardBag;
BizcardBag.Push(Bizcard());
BizcardBag.Push(Bizcard());
BizcardBag.Push(Bizcard());
BizcardBag.Push(Bizcard());//Error may happen here since Push() it need
//expanding capacity(origin value: 3)
/*1.as predict, Push success if change size process is directly in Push()
2.when turn to ChangeSize1D(), same error occur
2.1 when change to private member func, no error
2.2 when change to public member func, no error
2.3 when change to private unbinding friend func, same error occur;means private or public doesnt effect behaviour
2.4 when change to private binding friend func, same error occur
*/
return EXIT_SUCCESS;
}
#CMakeLists.txt
cmake_minimum_required(VERSION 2.6)
project(BugReproduct)
include_directories("${PROJECT_SOURCE_DIR}/Bizcard")
add_subdirectory("${PROJECT_SOURCE_DIR}/Bizcard")
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED true)
add_executable(BugReproduct ArrayExpansion.cpp)
target_link_libraries(BugReproduct Bizcard)
#Bizcard/CMakeList.txt
add_library(Bizcard Bizcard.cpp)
Problem SOLVED, this error happened because I pass the pointer directly to friend func, thus friend func would hold a copy but not reference or pointer to it. When I changed the destination the copied "array" pointed to in friend func, which changed the address value it saved, such process do nothing to the real array pointer outside, leading to error when I access the extra alloc element.
This issue can be another footnote about how dangerous pointer is and how much effort should be made before using pointer prefectly.
Profound appreciate to all the help you ever gave. Thank you all.

Delete object after using it in function C++

I have a question about delete and memory leak in C++. Considered the code below:
class AnObject{
public:
AnObject* Foo(){
// how can I delete this object ???
AnObject* obj = new AnObject();
...
return obj;
}
};
int main(){
...
AnObject* x = new AnObject();
AnObject* result = x->Foo();
delete x;
return 0;
}
My question is how can I delete the pointer in fuction AnObject::Foo() ???
// I read some suggestions who required changing the function, don't create an object with the word new in a fucntion. But does it exist a method to delete this pointer ?
You would do so by deleting this within AnObject::Foo but I would strongly discourage you from doing so. In this case, you do not need pointers at all:
class AnObject{
public:
AnObject Foo(){
return AnObject{};
}
};
int main()
{
AnObject x{};
AnObject result = x.Foo();
return 0;
}
If for whatever reason you really do need pointers, consider smart pointers
#include <memory>
class AnObject{
public:
std::unique_ptr<AnObject> Foo(){
return std::make_unique<AnObject>();
}
};
int main()
{
std::unique_ptr<AnObject> x = std::make_unique<AnObject>();
std::unique_ptr<AnObject> result = x->Foo();
return 0;
}
In both cases, you do not need to delete anything as you are using RAII semantics to handle your memory cleanup via scope.

Valgrind complains about a memory leak but I'm calling new and delete

I have used pointers to create an array and then wrote a delete procedure in the destructor
class cBuffer{
private:
struct entry {
uint64_t key;
uint64_t pc;
};
entry *en;
public:
cBuffer(int a, int b, int mode)
{
limit = a;
dist = b;
md = mode;
en = new entry[ limit ];
for (int i=0; i<limit; i++) {
en[i].key = 0;
en[i].pc = 0;
}
};
~cBuffer() { delete [] en; }
...
}
In another class I use cBuffer like this:
class foo() {
cBuffer *buf;
foo()
{
buf = new cBuffer(gSize, oDist, Mode);
}
};
However, valgrind complains about the new operator
==20381== 16,906,240 bytes in 32 blocks are possibly lost in loss record 11,217 of 11,221
==20381== at 0x4A0674C: operator new[](unsigned long) (vg_replace_malloc.c:305)
==20381== by 0x166D92F8: cBuffer::cBuffer(int, int, int)
cBuffer *buf;
foo()
{
buf = new cBuffer(gSize, oDist, Mode);
}
You need to call
delete buf;
Since you explicitly called new
Your class foo will cause your leak, since you never delete the dynamically allocated cBuffer. The solution is simple: there's no need for dynamic allocation at all here.
class foo {
cBuffer buf; // An object, not a pointer
foo() : buf(gSize, oDist, Mode) {}
};
More generally, when you do need dynamic allocation, be careful that you always delete what you new. The most reliable way to do this is to use RAII types such as containers and smart pointers to manage all dynamic resources for you.

How to avoid successive deallocations/allocations in C++?

Consider the following code:
class A
{
B* b; // an A object owns a B object
A() : b(NULL) { } // we don't know what b will be when constructing A
void calledVeryOften(…)
{
if (b)
delete b;
b = new B(param1, param2, param3, param4);
}
};
My goal: I need to maximize performance, which, in this case, means minimizing the amount of memory allocations.
The obvious thing to do here is to change B* b; to B b;. I see two problems with this approach:
I need to initialize b in the constructor. Since I don't know what b will be, this means I need to pass dummy values to B's constructor. Which, IMO, is ugly.
In calledVeryOften(), I'll have to do something like this: b = B(…), which is wrong for two reasons:
The destructor of b won't be called.
A temporary instance of B will be constructed, then copied into b, then the destructor of the temporary instance will be called. The copy and the destructor call could be avoided. Worse, calling the destructor could very well result in undesired behavior.
So what solutions do I have to avoid using new? Please keep in mind that:
I only have control over A. I don't have control over B, and I don't have control over the users of A.
I want to keep the code as clean and readable as possible.
I liked Klaim's answer, so I wrote this up real fast. I don't claim perfect correctness but it looks pretty good to me. (i.e., the only testing it has is the sample main below)
It's a generic lazy-initializer. The space for the object is allocated once, and the object starts at null. You can then create, over-writing previous objects, with no new memory allocations.
It implements all the necessary constructors, destructor, copy/assignment, swap, yadda-yadda. Here you go:
#include <cassert>
#include <new>
template <typename T>
class lazy_object
{
public:
// types
typedef T value_type;
typedef const T const_value_type;
typedef value_type& reference;
typedef const_value_type& const_reference;
typedef value_type* pointer;
typedef const_value_type* const_pointer;
// creation
lazy_object(void) :
mObject(0),
mBuffer(::operator new(sizeof(T)))
{
}
lazy_object(const lazy_object& pRhs) :
mObject(0),
mBuffer(::operator new(sizeof(T)))
{
if (pRhs.exists())
{
mObject = new (buffer()) T(pRhs.get());
}
}
lazy_object& operator=(lazy_object pRhs)
{
pRhs.swap(*this);
return *this;
}
~lazy_object(void)
{
destroy();
::operator delete(mBuffer);
}
// need to make multiple versions of this.
// variadic templates/Boost.PreProccesor
// would help immensely. For now, I give
// two, but it's easy to make more.
void create(void)
{
destroy();
mObject = new (buffer()) T();
}
template <typename A1>
void create(const A1 pA1)
{
destroy();
mObject = new (buffer()) T(pA1);
}
void destroy(void)
{
if (exists())
{
mObject->~T();
mObject = 0;
}
}
void swap(lazy_object& pRhs)
{
std::swap(mObject, pRhs.mObject);
std::swap(mBuffer, pRhs.mBuffer);
}
// access
reference get(void)
{
return *get_ptr();
}
const_reference get(void) const
{
return *get_ptr();
}
pointer get_ptr(void)
{
assert(exists());
return mObject;
}
const_pointer get_ptr(void) const
{
assert(exists());
return mObject;
}
void* buffer(void)
{
return mBuffer;
}
// query
const bool exists(void) const
{
return mObject != 0;
}
private:
// members
pointer mObject;
void* mBuffer;
};
// explicit swaps for generality
template <typename T>
void swap(lazy_object<T>& pLhs, lazy_object<T>& pRhs)
{
pLhs.swap(pRhs);
}
// if the above code is in a namespace, don't put this in it!
// specializations in global namespace std are allowed.
namespace std
{
template <typename T>
void swap(lazy_object<T>& pLhs, lazy_object<T>& pRhs)
{
pLhs.swap(pRhs);
}
}
// test use
#include <iostream>
int main(void)
{
// basic usage
lazy_object<int> i;
i.create();
i.get() = 5;
std::cout << i.get() << std::endl;
// asserts (not created yet)
lazy_object<double> d;
std::cout << d.get() << std::endl;
}
In your case, just create a member in your class: lazy_object<B> and you're done. No manual releases or making copy-constructors, destructors, etc. Everything is taken care of in your nice, small re-usable class. :)
EDIT
Removed the need for vector, should save a bit of space and what-not.
EDIT2
This uses aligned_storage and alignment_of to use the stack instead of heap. I used boost, but this functionality exists in both TR1 and C++0x. We lose the ability to copy, and therefore swap.
#include <boost/type_traits/aligned_storage.hpp>
#include <cassert>
#include <new>
template <typename T>
class lazy_object_stack
{
public:
// types
typedef T value_type;
typedef const T const_value_type;
typedef value_type& reference;
typedef const_value_type& const_reference;
typedef value_type* pointer;
typedef const_value_type* const_pointer;
// creation
lazy_object_stack(void) :
mObject(0)
{
}
~lazy_object_stack(void)
{
destroy();
}
// need to make multiple versions of this.
// variadic templates/Boost.PreProccesor
// would help immensely. For now, I give
// two, but it's easy to make more.
void create(void)
{
destroy();
mObject = new (buffer()) T();
}
template <typename A1>
void create(const A1 pA1)
{
destroy();
mObject = new (buffer()) T(pA1);
}
void destroy(void)
{
if (exists())
{
mObject->~T();
mObject = 0;
}
}
// access
reference get(void)
{
return *get_ptr();
}
const_reference get(void) const
{
return *get_ptr();
}
pointer get_ptr(void)
{
assert(exists());
return mObject;
}
const_pointer get_ptr(void) const
{
assert(exists());
return mObject;
}
void* buffer(void)
{
return mBuffer.address();
}
// query
const bool exists(void) const
{
return mObject != 0;
}
private:
// types
typedef boost::aligned_storage<sizeof(T),
boost::alignment_of<T>::value> storage_type;
// members
pointer mObject;
storage_type mBuffer;
// non-copyable
lazy_object_stack(const lazy_object_stack& pRhs);
lazy_object_stack& operator=(lazy_object_stack pRhs);
};
// test use
#include <iostream>
int main(void)
{
// basic usage
lazy_object_stack<int> i;
i.create();
i.get() = 5;
std::cout << i.get() << std::endl;
// asserts (not created yet)
lazy_object_stack<double> d;
std::cout << d.get() << std::endl;
}
And there we go.
Simply reserve the memory required for b (via a pool or by hand) and reuse it each time you delete/new instead of reallocating each time.
Example :
class A
{
B* b; // an A object owns a B object
bool initialized;
public:
A() : b( malloc( sizeof(B) ) ), initialized(false) { } // We reserve memory for b
~A() { if(initialized) destroy(); free(b); } // release memory only once we don't use it anymore
void calledVeryOften(…)
{
if (initialized)
destroy();
create();
}
private:
void destroy() { b->~B(); initialized = false; } // hand call to the destructor
void create( param1, param2, param3, param4 )
{
b = new (b) B( param1, param2, param3, param4 ); // in place new : only construct, don't allocate but use the memory that the provided pointer point to
initialized = true;
}
};
In some cases a Pool or ObjectPool could be a better implementation of the same idea.
The construction/destruction cost will then only be dependante on the constructor and destructor of the B class.
How about allocating the memory for B once (or for it's biggest possible variant) and using placement new?
A would store char memB[sizeof(BiggestB)]; and a B*. Sure, you'd need to manually call the destructors, but no memory would be allocated/deallocated.
void* p = memB;
B* b = new(p) SomeB();
...
b->~B(); // explicit destructor call when needed.
If B correctly implements its copy assignment operator then b = B(...) should not call any destructor on b. It is the most obvious solution to your problem.
If, however, B cannot be appropriately 'default' initialized you could do something like this. I would only recommend this approach as a last resort as it is very hard to get safe. Untested, and very probably with corner case exception bugs:
// Used to clean up raw memory of construction of B fails
struct PlacementHelper
{
PlacementHelper() : placement(NULL)
{
}
~PlacementHelper()
{
operator delete(placement);
}
void* placement;
};
void calledVeryOften(....)
{
PlacementHelper hp;
if (b == NULL)
{
hp.placement = operator new(sizeof(B));
}
else
{
hp.placement = b;
b->~B();
b = NULL; // We can't let b be non-null but point at an invalid B
}
// If construction throws, hp will clean up the raw memory
b = new (placement) B(param1, param2, param3, param4);
// Stop hp from cleaning up; b points at a valid object
hp.placement = NULL;
}
A quick test of Martin York's assertion that this is a premature optimisation, and that new/delete are optimised well beyond the ability of mere programmers to improve. Obviously the questioner will have to time his own code to see whether avoiding new/delete helps him, but it seems to me that for certain classes and uses it will make a big difference:
#include <iostream>
#include <vector>
int g_construct = 0;
int g_destruct = 0;
struct A {
std::vector<int> vec;
A (int a, int b) : vec((a*b) % 2) { ++g_construct; }
~A() {
++g_destruct;
}
};
int main() {
const int times = 10*1000*1000;
#if DYNAMIC
std::cout << "dynamic\n";
A *x = new A(1,3);
for (int i = 0; i < times; ++i) {
delete x;
x = new A(i,3);
}
#else
std::cout << "automatic\n";
char x[sizeof(A)];
A* yzz = new (x) A(1,3);
for (int i = 0; i < times; ++i) {
yzz->~A();
new (x) A(i,3);
}
#endif
std::cout << g_construct << " constructors and " << g_destruct << " destructors\n";
}
$ g++ allocperf.cpp -oallocperf -O3 -DDYNAMIC=0 -g && time ./allocperf
automatic
10000001 constructors and 10000000 destructors
real 0m7.718s
user 0m7.671s
sys 0m0.030s
$ g++ allocperf.cpp -oallocperf -O3 -DDYNAMIC=1 -g && time ./allocperf
dynamic
10000001 constructors and 10000000 destructors
real 0m15.188s
user 0m15.077s
sys 0m0.047s
This is roughly what I expected: the GMan-style (destruct/placement new) code takes twice as long, and is presumably doing twice as much allocation. If the vector member of A is replaced with an int, then the GMan-style code takes a fraction of a second. That's GCC 3.
$ g++-4 allocperf.cpp -oallocperf -O3 -DDYNAMIC=1 -g && time ./allocperf
dynamic
10000001 constructors and 10000000 destructors
real 0m5.969s
user 0m5.905s
sys 0m0.030s
$ g++-4 allocperf.cpp -oallocperf -O3 -DDYNAMIC=0 -g && time ./allocperf
automatic
10000001 constructors and 10000000 destructors
real 0m2.047s
user 0m1.983s
sys 0m0.000s
This I'm not so sure about, though: now the delete/new takes three times as long as the destruct/placement new version.
[Edit: I think I've figured it out - GCC 4 is faster on the 0-sized vectors, in effect subtracting a constant time from both versions of the code. Changing (a*b)%2 to (a*b)%2+1 restores the 2:1 time ratio, with 3.7s vs 7.5]
Note that I've not taken any special steps to correctly align the stack array, but printing the address shows it's 16-aligned.
Also, -g doesn't affect the timings. I left it in accidentally after I was looking at the objdump to check that -O3 hadn't completely removed the loop. That pointers called yzz because searching for "y" didn't go quite as well as I'd hoped. But I've just re-run without it.
Are you sure that memory allocation is the bottleneck you think it is? Is B's constructor trivially fast?
If memory allocation is the real problem, then placement new or some of the other solutions here might well help.
If the types and ranges of the param[1..4] are reasonable, and the B constructor "heavy", you might also consider using a cached set of B. This presumes you are actually allowed to have more than one at a time, that it does not front a resource for example.
Like the others have already suggested: Try placement new..
Here is a complete example:
#include <new>
#include <stdio.h>
class B
{
public:
int dummy;
B (int arg)
{
dummy = arg;
printf ("C'Tor called\n");
}
~B ()
{
printf ("D'tor called\n");
}
};
void called_often (B * arg)
{
// call D'tor without freeing memory:
arg->~B();
// call C'tor without allocating memory:
arg = new(arg) B(10);
}
int main (int argc, char **args)
{
B test(1);
called_often (&test);
}
I'd go with boost::scoped_ptr here:
class A: boost::noncopyable
{
typedef boost::scoped_ptr<B> b_ptr;
b_ptr pb_;
public:
A() : pb_() {}
void calledVeryOften( /*…*/ )
{
pb_.reset( new B( params )); // old instance deallocated
// safely use *pb_ as reference to instance of B
}
};
No need for hand-crafted destructor, A is non-copyable, as it should be in your original code, not to leak memory on copy/assignment.
I'd suggest to re-think the design though if you need to re-allocate some inner state object very often. Look into Flyweight and State patterns.
Erm, is there some reason you can't do this?
A() : b(new B()) { }
void calledVeryOften(…)
{
b->setValues(param1, param2, param3, param4);
}
(or set them individually, since you don't have access to the B class - those values do have mutator-methods, right?)
Just have a pile of previously used Bs, and re-use them.