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).
Related
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.
I am working on an open-source library that has a memory leak in it. The library is a data streaming service built around boost::asio. The server side uses heap memory management system which provides memory to hold a finite number of samples while they wait to get pushed accross a tcp connection. When the server is first constructed, a heap of memory for all the old samples is allocated. From this heap, after a sample is passed accross the socket, the memory is returned to the heap.
This is fine, unless all that pre-allocated heap is already taken. Here is the function that creates a 'sample':
sample_p new_sample(double timestamp, bool pushthrough) {
sample *result = pop_freelist();
if (!result){
result = new(new char[sample_size_]) sample(fmt_, num_chans_, this);
}
return sample_p(result);
}
sample_p is just a typedef'd smart pointer templated to the sample class.
The offending line is in the middle. When there isn't a chunk of memory on the freelist, we need to make some. This leaks memory.
My question is why is this happening? Since I shove the new sample into a smart pointer, shouldn't the memory be freed when it goes out of scope (it gets popped off of a stack later on.)? Do I need to somehow handle the memory allocated on the inside---i.e. the memory allocated by new char[sample_size_]? If yes, how can I do that?
Edit:
#RichardHodges here is a compile-able MCVE. This is highly simplified but I think it captures exactly the problem I am facing in the original code.
#include <boost/intrusive_ptr.hpp>
#include <boost/lockfree/spsc_queue.hpp>
#include <iostream>
typedef boost::intrusive_ptr<class sample> sample_p;
typedef boost::lockfree::spsc_queue<sample_p> buffer;
class sample {
public:
double data;
class factory{
public:
friend class sample;
sample_p new_sample(int size, double data) {
sample* result = new(new char[size]) sample(data);
return sample_p(result);
}
};
sample(double d) {
data = d;
}
void operator delete(void *x) {
delete[](char*)x;
}
/// Increment ref count.
friend void intrusive_ptr_add_ref(sample *s) {
}
/// Decrement ref count and reclaim if unreferenced.
friend void intrusive_ptr_release(sample *s) {
}
};
void push_sample(buffer &buff, const sample_p &samp) {
while (!buff.push(samp)) {
sample_p dummy;
buff.pop(dummy);
}
}
int main(void){
buffer buff(1);
sample::factory factory_;
for (int i = 0; i < 10; i++)
push_sample(buff, factory_.new_sample(100,0.0));
std::cout << "press any key to exit" << std::endl;
char foo;
std::cin >> foo;
return 0;
}
When I step through the code, I note that my delete operator never gets called on the sample pointers. I guess that the library I'm working on (which again, I didn't write, so I am still learning its ways) is mis-using the intrusive_ptr type.
You are allocating the memory with new[] so you need to deallocate it with delete[] (on a char*). The smart pointer probably calls delete by default, so you should provide a custom deleter that calls delete[] (after manually invoking the destructor of the sample). Here is an example using std::shared_ptr.
auto s = std::shared_ptr<sample>(
new (new char[sizeof(sample)]) sample,
[](sample* p) {
p->~sample();
delete[] reinterpret_cast<char*>(p);
}
);
However, why you are using placement new when your buffer only contains one object? Why not just use regular new instead?
auto s = std::shared_ptr<sample>(new sample);
Or even better (with std::shared_ptr), use a factory function.
auto s = std::make_shared<sample>();
With JsonCpp I want to serialize big objects with limited stack resources on an embedded device. All the examples I found are using stack objects which will be copied into each other (I guess). I want to reduce the copying the Json::Value objects all the time, but still using clustered code -- so that each object just needs to know how to serialize itself. I prepared a minimal example, which orientates to the described memory management from this answer https://stackoverflow.com/a/42829726
But in my example (in the end) there is still an not needed/wanted copy:
(*p)["a"] = *a.toJson(); // value will be copied into new instance
Can this be avoided somehow with JsonCpp?
struct itoJson
{
std::shared_ptr<Json::Value> toJson();
};
struct A: itoJson
{
int i;
std::shared_ptr<Json::Value> toJson()
{
std::shared_ptr<Json::Value> p = std::shared_ptr<Json::Value>(new Json::Value());
(*p)["i"] = i;
return p;
}
};
struct B: itoJson
{
int x;
A a;
std::shared_ptr<Json::Value> toJson()
{
std::shared_ptr<Json::Value> p = std::shared_ptr<Json::Value>(new Json::Value());
(*p)["x"] = x;
(*p)["a"] = *a.toJson(); // value will be copied into new instance
return p;
}
};
JsonCpp does not support move semantics — this is issue #223.
Until it does, you cannot entirely avoid copies.
However, if you make your code simple by getting rid of the needless dynamic allocation and smart pointers, you may get lucky and see your compiler optimising away some of it (via mechanisms like return value optimisation). But not all of it.
I'm looking for a method to dynamically create new class objects during runtime of a program. So far what I've read leads me to believe it's not easy and normally reserved for more advanced program requirements.
What I've tried so far is this:
// create a vector of type class
vector<class_name> vect;
// and use push_back (method 1)
vect.push_back(*new Object);
//or use for loop and [] operator (method 2)
vect[i] = *new Object;
neither of these throw errors from the compiler, but I'm using ifstream to read data from a file and dynamically create the objects... the file read is taking in some weird data and occasionally reading a memory address, and it's obvious to me it's due to my use/misuse of the code snippet above.
The file read code is as follows:
// in main
ifstream fileIn
fileIn.open( fileName.c_str() );
// passes to a separate function along w/ vector
loadObjects (fileIn, vect);
void loadObjects (ifstream& is, vector<class_name>& Object) {
int data1, data2, data3;
int count = 0;
string line;
if( is.good() ){
for (int i = 0; i < 4; i++) {
is >> data1 >> data2 >> data3;
if (data1 == 0) {
vect.push_back(*new Object(data2, data3) )
}
}
}
}
vector<Object> vect;
vect.push_back(Object()); // or vect.emplace_back();
That's it. That is the correct way, period. Any problems you are describing with reading objects from a file are a seperate matter, and we'd need to see that code in order to help you figure out what is wrong.
If you need polymorphism, then use a smart pointer:
vector<unique_ptr<Base>> vect;
vect.emplace_back(new Derived);
If you are, for some reason, constrained from using smart pointers, the old fashioned, error prone way to do it is like this:
vector<Base *> vect;
vect.push_back(new Derived);
....
for (int i=0; i<vect.size(); ++i)
{
delete vect[i];
vect[i] = NULL;
}
This is, of course, not exception safe.
If you absolutely have to use pointers (your objects store large data sets internally) then you should change your code to:
// create a vector of type class
vector<class*> vect;
// and use push_back (method 1)
vect.push_back(new Object);
//or use for loop and [] operator (method 2)
vect[i] = new Object;
Keep in mind that you'll have to delete your objects at some point.
vector<classType> vect;
declares vector container which contains type of classType, but you are adding a pointer to classType into vect, which will make compiler unhappy indeed.
If you need to present object's polymorphism in vector container, you need to store pointer to object, change your vect type to:
vector<std::shared_ptr<classType> > vect;
Declaring dynamic objects uses the following format:
TypeName * Name = new TypeName
you're going a little to fast with your vector, what you need to do is create a new object of class Object, THEN push it into the vector.
Object * MyObj = new Object //allocate space for new object
vect.push_back(MyObj) //push back new object
REMEMBER to delete what ever you allocate, which means looping through each element at the end to delete its member:
for(int i = 0; i < vectLen; i++) //probably will be replaced with iterators for vectors
{
delete vect[i];
}
read up on dynamic allocation more in depth here
For example, i have next code:
#include <set>
using namespace std;
struct SomeStruct
{
int a;
};
int main ()
{
set<SomeStruct *> *some_cont = new set<SomeStruct *>;
set<SomeStruct *>::iterator it;
SomeStruct *tmp;
for (int i = 0 ; i < 1000; i ++)
{
tmp = new SomeStruct;
tmp->a = i;
some_cont->insert(tmp);
}
for (it = some_cont->begin(); it != some_cont->end(); it ++)
{
delete (*it);
}
some_cont->clear(); // <<<<THIS LINE
delete some_cont;
return 0;
}
Does "THIS LINE" need to be called before deleting some_cont for avoiding memory leaks or destructor will be called automatically?
You don't need to call it, destructor will be called for sure.
No, there is no need to clear the set before destroying it.
Note that there is very rarely a need to allocate an std::set (or any standard container) manually. You'd be much better off just putting it in automatic storage and letting C++ handle the cleanup for you:
So instead of
set<SomeStruct *> *some_cont = new set<SomeStruct *>;
use
set<SomeStruct *> some_cont;
then change all some_cont-> to some_cont. and remove the delete some_cont (the container will be destroyed when main exits automatically.
The advantage to do things this way are:
You don't need to remember to delete the container, and
You don't need to do an expensive memory allocation up front.
It's also far more idomatic C++ to put things in automatic storage.
No, you don't need to explicitly clear a set before destroying the set.
OTOH, you do have a number of other problems ranging from lousy (Java-like) design, to incorrect syntax, to a missing operator to lots of potential memory leaks. While some of the design might make sense in Java or C#, it's a really poor idea in C++. Once we get rid of the most egregious problems, what we have left is something like this:
#include <set>
struct SomeStruct
{
int a;
SomeStruct(int i) : a(i) {}
bool operator<(SomeStruct const &other) const { return a < other.a; }
};
int main ()
{
std::set<SomeStruct> some_cont;
for (int i = 0 ; i < 1000; i ++)
{
SomeStruct tmp(i);
some_cont.insert(tmp);
}
return 0;
}
No it is not, this will be done automatically in the set's destructor.
The STL containers automatically free any memory they own. So in your case the place allocated to store your SomeStruct* will be freed by the destructor of set. Note that the destructor of set does not call any destructors of SomeStruct, so it's good you iterate over them to delete them yourself.