0

I'm new to std::shared_ptr and std::set. For the following code, I want to know how I can delete the edge from edges_.

edges_ is declared as std::set<std::shared_ptr<Edge>> edges_; and I want to delete the edge referenced by the shared pointer stored in the std::set. My code for the part is here, but there seems to be problem.

auto findEdge = findLinkingNode1->second->edges_.find(edge);
findLinkingNode1->second->edges_.erase(findEdge);

Error:

test8c(3034,0x7fff78df2000) malloc: *** error for object 0x7f8553403350: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6

How can I delete the edge from edges_, which is managed through shared pointers, considering that the shared pointers are stored in a std::set?

iteong
  • 715
  • 3
  • 10
  • 26
  • You should check the return from find in case it wasn't successful. Other than that, was the pointer stored in the shared pointer you are trying to destroy allocated on the heap? How was it allocated? – Robert Prévost Sep 17 '16 at 16:49
  • Are `Edge`s polymorphic or do they contain large amounts of data? If not, then why use shared pointers at all? Value semantics can be a big win. – Daniel Jour Sep 17 '16 at 16:53
  • The edge that is stored in edges_ is a shared pointer. It is converted from an edge to a shared pointer through std::make_shared. "new" was not used to make the object that the pointers are pointing to, so it is not allocated on the heap I think. As for the edges, yes they are polymorphic coz a generic template class of Graph is used with function template for different types, and the node and edge structs are part of that graph class. – iteong Sep 17 '16 at 17:02
  • findOrig->second->edges_.insert(std::make_shared(Edge (findOrig->second, findDest->second, val) )); – iteong Sep 17 '16 at 17:04
  • Regarding polymorphic: Does `Edge` contain a virtual member function? – Daniel Jour Sep 17 '16 at 17:19
  • struct Edge { std::weak_ptr orig; std::weak_ptr dest; E val_; Edge(std::shared_ptr o, std::shared_ptr d, E x); Edge() {}; void printEdge(); ~Edge(); }; – iteong Sep 17 '16 at 17:21
  • Your class is not polymorphic, it's a simple data object carrying two pointers and some data. My advice would be to get rid of the shared pointers and just store the edges directly in the set. (At least is the data isn't that large, for example an integer for the weight of the edge) – Daniel Jour Sep 17 '16 at 17:29

1 Answers1

1

It's just guessing, but given the code you provide ...

auto findEdge = findLinkingNode1->second->edges_.find(edge);
findLinkingNode1->second->edges_.erase(findEdge);

... I'd say your issue is that you're erasing edges_.end() which is not allowed (probably undefined behavior):

The iterator pos must be valid and dereferenceable. Thus the end() iterator (which is valid, but is not dereferencable) cannot be used as a value for pos.

The variable findEdge will be equal to edges_.end() if the given edge was not found in the set. To find an element, std::set uses a Compare object whose type is defined via the second template parameter ...

std::set<std::shared_ptr<Edge>> edges_;

... which you didn't specify, thus it's defaulting to std::less<std::shared_ptr<Edge>> which in turn calls the operator< of the shared pointer, which ...

Note that the comparison operators for shared_ptr simply compare pointer values; the actual objects pointed to are not compared.

... does not compare the objects but only the pointers. Therefore, if the pointers used for inserting and searching are not pointing to exactly the same (as in identical, not only "equal") object, you've signed up for trouble.


The above was a guess, but given your comment ...

findOrig->second->edges_.insert(std::make_shared<Edge>(Edge (findOrig->second, findDest->second, val) ));

... makes it a fact, as there's (almost) no way to get hold of the pointer returned by make_shared.

Solution: Implement a compare class for your set that compares the actual Edge objects. (Getting rid of the pointers isn't that straightforward because you said that Edge is polymorphic)

Morale: Always test for possible error conditions.

Daniel Jour
  • 15,896
  • 2
  • 36
  • 63
  • So the compare class you are talking about, is that for being able to delete the edge from edges_? How come the pointer returned by make_shared cannot be returned at all? So I cannot delete the edge at all? – iteong Sep 17 '16 at 17:20
  • The `edge` parameter to the find function would need to be the same (or a copy thereof) as the pointer returned by `make_shared` in the insert call. How do you get `edge`, i.e. what's assigned to it? – Daniel Jour Sep 17 '16 at 17:23
  • You mean what is inside the edge class? It's as mentioned above. – iteong Sep 17 '16 at 17:24