After a few years, I discovered a memory leak bug in my code. Unfortunately the bug was not causing any issues to be noticed until I found out about it indirectly.
Below is a function addElement() from class c_string which adds a new element to a chain. My old way of doing it is like this:
class c_string
{
private:
char *chain;
size_t chain_total;
public:
void addElement(char ch);
};
void c_string::addElement(char ch)
{
char *tmpChain = new char[chain_total+1];
for(size_t i=0;i<chain_total;i++)
tmpChain[i] = chain[i];
tmpChain[chain_total++] = ch;
delete chain;
chain = new char[chain_total];
chain = tmpChain;
}
I found out that by doing chain = tmpChain; I am causing a memory leak.
My question is, what is the best way to handle it?
Please note, in this class I am not using any STL function, because I am simply writing my own string.
The best way to do it is simply drop the second allocation, it serves no purpose.
void c_string::addElement(char ch)
{
char *tmpChain = new char[chain_total+1];
for(size_t i=0;i<chain_total;i++)
tmpChain[i] = chain[i];
tmpChain[chain_total++] = ch;
delete[] chain;
chain = tmpChain;
}
The above is correct and even has the strong exception guarantee.
Of course even if you do not want to use std::string, std::unique_ptr would is still safer than raw new+delete and you would get the rule of five for free instead of having to implement it on your own.
From performance standpoint, you might be interested in Why is it common practice to double array capacity when full? and of course std::memcpy or std::copy instead of the manual loop.
Related
I'm learning C++ and especially OO Programming.
My program use pointers to deal with Dynamic memory allocation.
While creating my default constructor, I was boring about repeat myself with
myInt = new int;
myOtherInt = new int;
etc..
So my question is : is there a way to write something like :
myInt, myOtherInt = new int;
Here's my constructor code :
Annonce::Annonce(string Titre, long double Prix, string Intro, string Description, vector<vector<string>> ImgUrls) {
titre = new string;
intro = new string;
description = new string;
imgUrls = new vector<vector<string>>;
prix = new long double;
id = new size_t;
*id = nbAnnonces;
*titre = std::move(Titre);
*prix = Prix;
*intro = std::move(Intro);
*description = std::move(Description);
*imgUrls = std::move(ImgUrls);
}
There is no shortcut for allocating multiple variables from dynamic memory.
The functions for allocating memory return a single memory address (pointer). Each variable should have its own, unique, location in memory.
The syntax of the C++ language would need to change in order to support the dynamic memory functions returning multiple addresses (pointers).
One recommendation is to reduce the quantity of memory allocations. Ask yourself, "Do I really need to allocate from dynamic memory?" before allocating from dynamic memory.
Is there a way to write something like :
myInt, myOtherInt = new int;
Yes, two ways. But the first is more general than what you specifically asked for...
1. Prefer value-types over reference-types
If you don't know what these are: Value types and Reference Types (Wikipedia).
In some programming languages, almost all of your variables, function parameters, class fields, etc - are references. A prominent example of this is Java. But in C++ - especially these days - we prefer values to references unless there's a good reason not to use values directly. Value semantics are commonly used and well-supported in the language, and most work with them is easier. See also:
Why are pointers not recommended when coding with C++11
Specifically, that means that, when defining a struct or a class, we'll give it non-pointer members. In your case:
class Announcement {
public:
using url_type = std::string; // perhaps use a URL library?
using image_urls_container_type = std::unoredered_set<url_type>;
// I'm guessing the URLs aren't really ordered
std::string title;
std::string introduction;
std::string description;
std::vector<image_urls_container_type> image_urls;
// Are the images really a sequence of indices? Shouldn't this be something like
// std::unordered_map<image_id_type,image_urls_container_type> image_urls ?
long double prize;
std::size_t id;
Announcement() = delete;
// constructors here, if you like
}
Now, I'm not saying this is necessarily the best possible definition or that it fits all your needs. But if you define it this way, you get:
No need to use new, ever.
No need to delete anything.
No chance of memory leaks (due to this class)
2. Otherwise, use std::unique_ptr's
The std::unique_ptr<T> class lets you avoid having to manage memory yourself - it takes care of that. So if you make your members std::unique_ptr's, you can initialize the value they point to using get(), e.g.:
void foo(int x) {
auto p = std::make_unique<p>();
p.get() = x;
// do stuff with p
// ...
// no need to delete p at the end of the function
}
First Pre Answer Suggestion: don't do it.
Second Pre Answer Suggestion: avoid self-managed memory allocation/deallocation and use STL containers and/or smart pointers (std::unique_ptr, std::shared_ptr, etc.) instead
Answer: no, as far I know you can't write something as
int * myInt, myOtherInt = new int;
that allocate both variables (with different allocated pointers).
But you can wrap the pointers in a class or struct that automatically allocate the contained pointer (and, maybe, destroy it in the destructor).
Just for fun... if you write a wrapper as follows
template <typename T>
struct wrappPnt
{
T * pnt = new T{};
T & operator * ()
{ return *pnt; }
T const & operator * () const
{ return *pnt; }
~wrappPnt ()
{ delete pnt; }
};
you can write your Annonce this way
struct Annonce
{
wrappPnt<std::string> titre, intro, description;
wrappPnt<std::vector<std::vector<std::string>>> imgUrls;
wrappPnt<long double> prix;
Annonce (std::string Titre, long double Prix, std::string Intro,
std::string Description,
std::vector<std::vector<std::string>> ImgUrls)
{
*titre = std::move(Titre);
*prix = Prix;
*intro = std::move(Intro);
*description = std::move(Description);
*imgUrls = std::move(ImgUrls);
}
};
First Post Answer Suggestion: don't do it.
Second Post Answer Suggestion: avoid self-managed memory allocation/deallocation and use STL containers and/or smart pointers (std::unique_ptr, std::shared_ptr, etc.) instead
If I have:
template<>
char *toBytes<uint64_t>(uint64_t src) {
char *data = new char[8];
//...stuff
return data;
}
template<>
void write<uint64_t>(char *dst, uint64_t src) {
char *srcBytes = toBytes(src);
for (int i = 0; i < 8; ++i) {
*(dst++) = *(srcBytes++); //am I leaking here?
}
}
that gets called with something like:
char *keyPtr = new char[27];
//...stuff
write(keyPtr, 1234ull);
//...write up to 27
If do delete[] keyPtr; would I have deleted srcBytes? I think the question is, on the line asking if I'm leaking, is that doing a copy and as a result deleting keyPtr leaves srcBytes still to be deleted?
Still learning C++ and it's not always clear to me when the copy constructor is called vs the assignment operator.
EDIT 1:
Fixed delete as per #Steephen's answer
EDIT 2
Add toBytes as per #WhozCraig's comment
You have to use
delete [] keyPtr;
instead of calling delete over for loop;
If you allocate memory using new[], you should use delete [], and if you use new, you should use delete. In your case you are using the former one.
I think the question is, on the line asking if I'm leaking, is that
doing a copy and as a result deleting keyPtr leaves srcBytes
If your program allocated memory for srcBytes using new operator you should delete it it as same way you do for keyPtr . Because resource handling by both pointers are independent even after your assignment in your case.
You have a memory leak. No, delete []-ing keyPtrhas nothing to do with srcBytes, an independent allocation. The two addressed buffers are unrelated (except for content due to your copy-code).
Apart from the obvious (using std::vector<> and letting RAII take over the memory management for all of this), a fairly minimal change to your code to plug the leak would loop something like this:
template<>
void write<uint64_t>(char *dst, uint64_t src)
{
char *srcBytes = toBytes(src);
std::copy(srcBytes, srcBytes+8, dst);
delete [] srcBytes;
}
or using a smart pointer:
template<>
void write<uint64_t>(char *dst, uint64_t src)
{
std::unique_ptr<char[]> srcBytes(toBytes(src));
std::copy(srcBytes.get(), srcBytes.get()+8, dst);
}
Both use the std::copy stock algorithm which both accomplishes what you seem to want, while retaining the original result of toBytes for proper cleanup. Which you choose (or perhaps something entirely different still) I leave to you.
Best of luck.
These are a few cases where you will leak the memory where you used "new":
The function runs out of scope before you could delete it and there is no pointer to the allocated memory outside of the function.
You forget to delete where appropriate
You mix delete and delete []
Exception is caught between the use of "new" and "delete".
Even as a beginner, it's a good idea to get familiar with smart pointers.
I have some code that contains a self-made hashtable using calloc and malloc for memory allocation. I would like to modify these parts using a shared_ptr with a custom deleter that frees automatically the allocated memory.
The code is part of the mmseg chinese segmenter algorithm, it is working great but is such a mess as it leaves memory leaks. I am considering to rewrite that code using a unordered_map or such, but for now I would like to make these changes.
I read the answers on similar questions, such as shared_ptr with malloc and free or Accessing calloc'd data through a shared_ptr, but I have problems to use that on the code below.
I have these lines where I am not able to wrap the calls with the smart pointer. So maybe somebody can help me out with this:
struct Word {
unsigned char nbytes; /* number of bytes */
char length; /* number of characters */
unsigned short freq;
char text[word_embed_len];
};
struct Entry {
Word *word;
Entry *next;
};
static Entry **new_bins = static_cast<Entry **>(std::calloc(init_size,
sizeof(Entry *)));
Entry *entry, ...;
...
new_bins[hash_val] = entry;
....
free(new_bins);
The above calloc call I would feed shared pointer with the result of calloc, such as
std::shared_ptr<Entry *> binsPtr(new_bins, freePtr());
I am not shure if this is correct.
mmseg uses a pool allocation routine with malloc(), which looks like this:
inline void *pool_alloc(int len) {
void *mem = _pool_base;
if (len <= _pool_size) {
_pool_size -= len;
_pool_base += len;
return mem;
}
_pool_base = static_cast<char *>(std::malloc(REALLOC_SIZE));
mem = _pool_base;
_pool_base += len;
_pool_size = REALLOC_SIZE - len;
return mem;
}
The allocator then is called like this:
Entry *entry = bins[h];
...
entry = static_cast<Entry *>(pool_alloc(sizeof(Entry)));
entry->word = word;
entry->next = NULL;
bins[h] = entry;
Is it possible to modify the pool_alloc routine such as I could wrap the malloc() with a shared pointer an define a custom deleter (maybe even skip the complete pool_alloc fct and just use a shared_ptr), something like
std::shared_ptr<Entry> entry((Entry *)malloc(sizeof(Entry)), freePtr());
struct freePtr {
void operator()(void* x) {
free(x);
}
};
Would be great if somebody could help me out on this. Thanks in advance!
Update:
I coded a simple memory pool class for my problem, so all pointers get destroyed automatically. The wrapped calloc() in the shared_ptr seems to work fine and works as expected. Valgrind reports no more memory leaks and errors.
OP writes:
I coded a simple memory pool class for my problem, so all pointers get destroyed automatically. The wrapped calloc() in the shared_ptr seems to work fine and works as expected. Valgrind reports no more memory leaks and errors.
In other words, changing the code fixed the bugs. :) This question could safely be deleted at this point.
pointer segfault problems...
I've been doing c++ for some weeks meanwhile but i ran again into that issue.
basically i have these classes given. I cant change them. I start with an instance of _ns3__importAuftragResponse kout;
class SOAP_CMAC _ns3__importAuftragResponse
{
public:
ns2__SOAPImportResult *return_;
...
class SOAP_CMAC ns2__SOAPImportResult
{
public:
bool *error;
int *numberOfIgnoreds;
....
My code needs to check for the numberOfIgnoreds
first approach
ns2__SOAPImportResult* imp_result;
imp_result = kout.return_;
int num;
num = *imp_result->numberOfIgnoreds;
or i use
ns2__SOAPImportResult imp_result;
imp_result = *(kout.return_);
int* num;
*num = *imp_result.numberOfIgnoreds;
I mostly get segmentation fault
I know generally what happens at runtime but cant come up with the correct ode. PLease help.
EDIT
made progress thx to your answer, Nawaz , but still need some understanding
ns2__SOAPImportResult * imp_ptr = new ns2__SOAPImportResult;
imp_ptr = kout.return_;
int * num = new (int);
// next line segfaults
*num = *imp_ptr->numberOfIgnoreds;
what's hard for me to understand is, how or why allocate memory for something that is already "there" as there is the member return_ of the object kout
So is it correct to say I need to allocate memory for the variable I assign it to (which is of same type of course)?
Most likely you've not allocated memory for the following members which you're using in the code you've quoted.
ns2__SOAPImportResult *return_; //in the class _ns3__importAuftragResponse
int *numberOfIgnoreds; //in the class ns2__SOAPImportResult
Other than this I don't see anything where things might go wrong!
Make sure you allocate memory for these members (and all other pointers in your program) before using them. You can use new to allocate memory. Or alternatively, you can use malloc() as well. Whatever you use, use it consistently, and deallocate the memory once you done, using delete or free() respectively!
This looks like gsoap. In that case you must use soap_malloc to allocate memory which you return.
For example on the FAQ page, you will find this example:
int ns__itoa(struct soap *soap, int i, char **a)
{ *a = (char*)soap_malloc(soap, 11);
sprintf(*a, "%d", i);
return SOAP_OK;
}
I have a vector with raw pointers (no, I cannot use smart pointers) and I want to add items to the list in a for loop. I've made a little trial project, and I wondered if this is considered good C++ code in terms of pointer management.
Please only consider raw pointer management, I am not interested in smart pointers for this particular problem I'm trying to solve.
A simple object:
class Request
{
public:
std::string name;
};
std::vector<Request*> requests;
for (int i = 0; i < 5; i++)
{
std::stringstream ss;
ss << "elemenent ";
ss << i;
std::string s = ss.str();
Request* req = new Request();
req->name = s;
requests.push_back(req);
}
EDIT:
So the problem I am trying to solve is adding the DOMNode* to a vector from this library.
I'm starting to get the feeling that trying to write a wrapper for the parts I need from this library for my project, is a bad idea. Or maybe the library is no good?
I haven't got it to work properly using smart_ptr, if anybody out there has, then I'd like to hear about it.
Well, this leaks memory, so it is bad. Can you use a Pointer Container?
The reason this code leaks is because you create objects on the heap using new, but you never call delete on them.
As for you comment, if you have an object that manually manages some resource, you need The Big Three.
I'll consider that you have a loop, at the end of the method, to call delete on each member of the vector.
There are still issues, specifically exception safety issues.
If anything throws between the creation of the Request and its registration in the vector, you've lost the memory. One solution is to temporarily use a scoped_ptr to hold on the memory, push_back with ptr.get() and then call the release method since now the memory is owned by the vector.
If anything throws between the point when you have created the items in the vector and the point you destroy them, you need to catch the exception, destroy the items, and then rethrow.
There might be others, but RAII has been invented for a reason, it's really difficult to do without (correctly...)
If you cannot use smart pointers, then use boost::ptr_vector.
Note that if you are using TinyXml, memory management in XmlNode is probably dictated by the library - recent history iirc is that many of your problems are associated with properly understanding the memory ownership and release paradigm for this library.
What memory management do I need to cleanup when using TinyXml for C++?
What is the best open XML parser for C++?
If you are not able (or allowed) to use smart pointers, probably you could make use of a simple memory manager like this:
template <class T>
class MemManager
{
public:
typedef std::vector<T*> Vec;
~MemManager ()
{
size_t sz = v_.size ();
for (size_t i = 0; i < sz; ++i)
delete v_[i];
}
T* pushNewObject ()
{
T* t = NULL;
try
{
t = new T;
if (t != NULL)
v_.push_back(t);
}
catch (std::bad_alloc& ex) { /* handle ex */ }
return t;
}
const Vec& objects() const { return v_; }
private:
Vec v_;
};
// test
{
MemManager<Request> mm;
for (int i = 0; i < 5; i++)
{
std::stringstream ss;
ss << "elemenent ";
ss << i;
std::string s = ss.str();
Request* req = mm.pushNewObject();
req->name = s;
}
} // all Request objects will be deleted here when
// the MemManager object goes out of scope.
A quick improvement could be to derive a class RequestVector from std::vector<Request*>, add a ClearRequests method (which deletes all the Request objects and clears the vector) and and make it's destructor call ClearRequests.
(Actually aggregating the vector in RequestVector could be a better choice, but a derived class is faster done).