shared_ptr gets destroyed before I can use it properly - c++

I have the following code, which is supposed to add a shared_ptr instance to an intrusive linked list by thread A. Some other consumer thread will then use it later on by removing it from the list. However at a certain point my shared_ptr seems to get destroyed and the reference to it in the linked list is no longer valid resulting in an Assert.
Can someone enlighten me on what I am doing wrong? I suspect it is because I create my original shared_ptr in a local scope and it just gets destroyed. Although the List should still have a reference to it??? (This is NOT production code)
EDIT:
Defintiions of variables used:
BaseHookQueueList* lst;
typedef boost::intrusive::list<QueueList> BaseHookQueueList;
class QueueList : public boost::intrusive::list_base_hook<>
// Making my BaseHookQueueList take a shared_ptr of pointing to type QueueList conflicts // with the list_base_hook because it does not seem to like shared_ptr...
////////////////////////////////////////////////////////////////////////////////////
if (dwWait == WAIT_OBJECT_0) //Wait is successfull
{
while(count != 100)
{
//Some new request arrived
boost::shared_ptr<QueueList> Qlist (new QueueList()); //Create shared_ptr instance
int temp = 0;
if (count > 5)
{
Qlist->SetName(names[temp]); // Fill up name property of QueueList object with some nonsense...
temp++;
}
else
{
Qlist->SetName(names[count]);
}
workerfunc(lst, Qlist); // Pass to worker func
count++;
}
} // shared_ptr goes out scope and I get ASSERT error from list!!
}
}
void workerfunc(BaseHookQueueList* l, LIST item) // LIST is a typedef shared_ptr<QueueList> LIST
{
{
boost::mutex::scoped_lock workerfunclock(listlock);
l->push_front(*item); //Add to list
}
//Scope of lock
{
boost::mutex::scoped_lock workerfuncconsoleLock(consolelock);
printf("Adding item to list...\n");
}
ReleaseSemaphore(hConsumer, 1, NULL); // Set conumser Semaphore to Signalled with number of items currently on the queue
}

l->push_front(*item); //Add to list
The dereference could be the problem. You are not passing a shred_ptr instance to the l list but the pointee itself. If that's not it, please post more complete and less confused test-case.

If BaseHookQueueList is an intrusive list like you said, then you should remember that intrusive list doesn't take the ownership of the objects. In this case your shared pointers have the ownership, and when they are destroyed, the object is destroyed too.
edit: Instead of intrusive list you could use a container like std::list or std::queue that can contain smart pointers.

In your worker function, you're storing the pointed-to item, rather than the shared pointer, so the shared-pointer's reference count is not incremented.

I guess item is wrong in this case.
As the operator returns a reference to your type. So you put a const ref into your list but not a copy of the shared_ptr.

Related

Safe to delete parent of vector of pointers when those pointers have been shared?

I'm getting memory leak issues in one of my applications that I'm going through and trying to fix. One of my suspected problem points is where I parse lines from a file into commands using BNFC:
void LineStreamScriptProvider::populateQueue()
{
if(shouldPopulate())
{
TasScript::ShowAbsyn shower;
std::string line;
while(queueSize() < 30 && !stream.eof())
{
std::getline(stream, line);
const char* lineCStr = line.c_str();
TasScript::Program* lineCmds = TasScript::pProgram(lineCStr);
TasScript::P* asLeaf = static_cast<TasScript::P*>(lineCmds);
TasScript::ListCommand* cList = asLeaf->listcommand_;
for_each(cList->begin(), cList->end(), [this, shower](TasScript::Command* cmd) {
// log_to_sd_out("Parsed command %s\n", shower->show(cmd));
std::shared_ptr<TasScript::Command> cmdShared(cmd);
pushToQueue(cmdShared);
});
}
if(stream.eof())
{
afterEOF();
}
}
}
For reference:
class P : public Program
{
public:
ListCommand *listcommand_;
// ...
class ListCommand : public Visitable, public std::vector<Command*>
{
// ...
BNFC constructs these with new and then returns the pointers. Is it safe to delete lineCmds without deleting the value held by cmdShared?
Sorry, I wasn't aware of BNFC and that it creates raw pointers for you.
Is it safe to delete lineCmds without deleting the value held by
cmdShared?
If you are creating a shared pointer from a raw pointer the shared pointer takes ownership of that resource. The shared pointer will maintain a reference count for that resource until it drops to zero, i.e. when all shared pointers for that resource go out of scope, at which point it will try to destroy the resource.
Here you are creating a shared pointer and passing it to a queue:
std::shared_ptr<TasScript::Command> cmdShared(cmd);
pushToQueue(cmdShared);
The shared pointer will take care of the memory management for you. So there is no need to explicitly call delete on the vector of commands. Once all shared pointers of type std::shared_ptr<TasScript::Command> are destroyed the resource is also destroyed.
So no, it is not safe to delete a vector of pointers in this case.
Another simpler solution is to take a copy of the TasScript::Command:
TasScript::Command cmdCopy(*cmd);
Then change pushToQueue() to accept by const TasScript::Command&, not by shared pointer. Then you don't have to worry about the pointer being destroyed since you have a copy of the value.
It looks like in your while loop you are leaking memory. Don't you have to delete lineCmds and cList?

Segmentation fault in access vector C++

I'm writing a simple multi-threading program to add and access member in a vector in a multiple thread:
Thread 1: Use push_back to add member to vector
Thread 2: Calling a function Iterate through vector and check if the member is already in the vector then return it, otherwise return NULL
Some time I faced the Segmentation fault at the thread 2. Is the vector is thread safety for doing what I mention above. I do not have any code to remove member from the vector, only adding more.
Here is the full code of function iterate the vector:
Scope* ScopeList::FindScope(int32_t domain, int32_t channel) {
Scope* findItem = new Scope(domain, channel);
Scope* resultItem = NULL;
for(uint32_t i = 0U; i < m_scope_list.size(); i++) {
if(m_scope_list.at(i) == NULL) {
continue;
}
if(m_scope_list.at(i)->isEqual(findItem)) {
resultItem = m_scope_list.at(i);
break;
}
}
delete findItem;
findItem = NULL;
return resultItem;
}
Here m_scope_list is a vector of Scope object, which isEqual function is define as follow:
bool Scope::isEqual(Scope* scope) {
if(scope == NULL||!this->m_domain ||!this->m_channel){
return false;
}
bool result = this->m_domain == scope->GetDomain() && this->m_channel == scope->GetChannel();
return result;
}
You need to synchronize both threads. Because a vector is not thread-safe. If you modify the vector from one thread and access from another then there is a high chance of getting a segmentation fault. You might want to look into uniqe_lock or lock_guard and mutex for details. If you don't understand anything about their usages then leave a comment. Happy Multithreading.
EDITED: From comment made by #GianPaolo
push_back will modify the internal state of the vector, in a way that can be not thread safe. if you call push_back when the vector as already reached its capacity, the current T[] array in use will be copied in a new T[] (of higher size), and the original will be deleted. Not something you can safely do while another thread is iterating on the vector

When creating a higher order map function should I use a pointer or a reference or a value?

I have the following piece of code in C++:
EventQueue * EventQueueNode::map(std::function<LoggerEvent *(LoggerEvent *)> func,
bool stop_propagate = true){
auto old_node = this->event_node;
this->event_node = func(this->event_node);
delete old_node;
return this->right()->map(func, stop_propagate);
};
This code breaks if the user returns the same pointer, but if I don't delete it, it will leak memory.
EventQueue is a circular doubly linked list. And it has a head, which hold both ends, but which functions as endpoint:
EventQueue * EventQueue::map(std::function<LoggerEvent *(LoggerEvent *)> func,
bool stop_propagate = false) {
if(stop_propagate)
return this;
return this->right()->map(func, true);
};
Now I have a problem. I really would like to write the map function as:
EventQueue * EventQueueNode::map(std::function<LoggerEvent(LoggerEvent)> func,
bool stop_propagate = true){
this->event_node = func(this->event_node);
return this->right()->map(func, stop_propagate);
};
Because the previous map needs to be destructed anyway and it doesn't cause memory leaks. And a map traditionally replaces a value. But then I also have to make event_node a value, which will cause it to be copied everywhere. I am quite a beginner, so I am getting stuck at the approach I should take.
What would be a good approach to tackle this problem?
Full code:
http://pastebin.com/NT1pD5ar (most code is in a construction state and there are more issues I have)
You can use smart pointers like shared_ptr<LoggerEvent> to store it in containers and pass it around. The object that the smart pointer points to will be destroyed once all copies of the smart pointer are destroyed.

Unwanted creation of object at same memory address

I haven't been working with C++ for a long time and now I need to do some small "project".
I reviewed few topics trying to find solution for my problem with no results...
Here is "pseudo-code" (Pair is my class):
Pair** pairs;
I get size of table from input and create table of pointers:
pairs = new Pair*[size];
I have a loop which creates some object and puts it's reference into table of pointers. More or less:
while (...)
{
Pair pair(...); // calling constructor, creating object type of Pair.
pairs[i] = &pair;
i++;
}
The problem is that &pair is the same number everytime (every step of loop).
Let's say the address of first created object is 1234.
So with every step in loop it overrides this object at 1234. So each pointer in pairs points to the same address -> same object.
I would like to force creating this object at new place in memory.
I've been trying to put those objects into other table and then pass their reference to table of pointers:
Pair* clearPairs = new Pair[size];
while (...)
{
clearPairs[i] = Pair(...);
pairs[i] = &clearPairs[i];
i++;
}
But problem still occurs.
Any tips?, mistakes/errors in my code (or thinking)? Shall I implement some "copying constructor"?
while (...)
{
Pair pair(...); // calling constructor, creating object type of Pair.
pairs[i] = &pair;
i++;
}
pair is allocated with automatic storage duration and goes out of scope upon each iteration of the loop. You are saving a pointer to an invalid object (a bunch of them).
You should use a collection of smart pointers if you really need pointers (this is true when objects cannot be copied or copies are expensive), which may not be necessary at all. Try this instead:
vector<Pair> pairs;
// and if you need pointers...
vector<unique_ptr<Pair>> pairs;
while(whatever) {
pairs.push_back(Pair(...));
// or...
pairs.push_back(unique_ptr<Pair>(new Pair(...)));
}

How to properly delete pointer from a std::list?

I'm creating an object via new, then later adding the pointer to an std::list once the object is set up.
What is the correct way of deleting a pointer and erasing the data from the list without causing memory leaks?
Instead of manual loop to search the element, I would rather use std::find_if
auto it = std::find_if(lst.begin(),
lst.end(),
[&val](datalist const &d) { return d.index == val; });
if ( it != lst.end() )
{
delete *it;
lst.erase(it);
}
That is not to say that you're doing it incorrectly.
However, your code will improve if you consider using some form of smart points, such as std::unique_ptr, std::shared_ptr, or boost's smart pointers, then you don't have to manage memory yourself.
If you change your std::list to hold datalist instances instead of datalist* pointers, then you don't have to delete the datalist instances manually anymore. When you remove an element from a std::list (or any other STL container, for that matter), the element's data is freed automatically for you. If the element is a class/struct with a destructor defined, the destructor will be called.
Try this:
std::list<datalist> m_DataList;
.
datalist AR; // <-- local variable on the stack, freed when out of scope
AR.index = ...;
AR.number = ...;
mylist.push_back(AR); // <-- pushes a copy-constructed instance of the variable
.
std::list<datalist>::iterator Iter1 = m_DataList.begin();
while(Iter1 != m_DataList.end())
{
if (Iter1->index == m_SomeVar)
{
m_DataList.erase(Iter1); // <-- copied datalist instance is freed automatically
break;
}
++Iter1;
}