I am trying to use the C++ "Clipper Library" (http://www.angusj.com/delphi/clipper.php), but when I try to return one of the objects from the clipper library from a function, it seems to become null or is altered somehow
Here is the function I wrote. The only relevant lines should be the last 3.
ClipperLib::PolyTree MeshHandler::trianglesToPolyTreeUnion(std::vector<Triangle> triangles)
{
// Make all of the triangles CW
for (auto& triangle : triangles)
{
triangle.makeClockwise();
}
// Set up the Clipper
ClipperLib::Clipper clipper;
// To take a union, add all the paths as "subject" paths
for (auto& triangle : triangles)
{
ClipperLib::Path triContour(3);
triContour[0] = convertGLMToClipperPoint(triangle.getVertex(0));
triContour[1] = convertGLMToClipperPoint(triangle.getVertex(1));
triContour[2] = convertGLMToClipperPoint(triangle.getVertex(2));
clipper.AddPath(triContour, ClipperLib::PolyType::ptSubject, true);
}
// Now get the PolyTree representing the contours
ClipperLib::PolyTree tree;
clipper.Execute(ClipperLib::ClipType::ctUnion, tree);
return tree;
}
When I call clipper.execute, it writes into the tree structure some contour information. It writes the correct information, and I've tested that it's correct. However, when I return the tree, it doesn't seem to copy anything, and the PolyTree that results from this function is empty.
I'm sure that there's nothing wrong with the library and that I'm just making a beginner c++ mistake here. Hopefully someone has an idea of what it might be.
Thanks!
edit: For reference, here is a documentation page for the polytree (http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Classes/PolyTree/_Body.htm)
edit: I thought the clipper library wasn't open source, but it is. Here is the code
typedef std::vector< IntPoint > Path;
typedef std::vector< Path > Paths;
class PolyNode;
typedef std::vector< PolyNode* > PolyNodes;
class PolyNode
{
public:
PolyNode();
Path Contour;
PolyNodes Childs;
PolyNode* Parent;
PolyNode* GetNext() const;
bool IsHole() const;
bool IsOpen() const;
int ChildCount() const;
private:
unsigned Index; //node index in Parent.Childs
bool m_IsOpen;
JoinType m_jointype;
EndType m_endtype;
PolyNode* GetNextSiblingUp() const;
void AddChild(PolyNode& child);
friend class Clipper; //to access Index
friend class ClipperOffset;
};
class PolyTree: public PolyNode
{
public:
~PolyTree(){Clear();};
PolyNode* GetFirst() const;
void Clear();
int Total() const;
private:
PolyNodes AllNodes;
friend class Clipper; //to access AllNodes
};
Before doing anything, make sure the following program works correctly:
int main()
{
PolyTree p1;
// fill PolyTree with some values that make sense (please add code to do this)
//...
PolyTree p2 = p1;
PolyTree p3;
p3 = p1;
}
That is basically what we want to test. If you can get this code to work (add the relevant headers and initializations necessary), then you can focus back on the function. If the code above doesn't work, then there is your answer.
You need to get the code above to produce the correct copy semantics, and even just important, when main() exits, no memory corruption occurs on the destruction of p1, p2, and p3.
So either you can fix the class to copy safely, or forget about it and live with a class that you have to handle very carefully and in limited situations (i.e. you can't reliably return copies of it as you're doing now).
For the record and combining all the responses in the lengthy discussion to the question.
Problems are:
The value returned is a local variable that goes out of scope. This invokes the PolyTree destructor
The PolyTree contains a vector of PolyNode * pointers. Those are allocated when clipper.Execute() is invoked.
However PolyTree::Clear() does delete the nodes... and Clear() is invoked by the destructor.
So within the function, the content is correct (allocated by Execute()), when passed outside, in the absence of copy constructors and operator=, the destructor of the local variable is invoked an the nodes are cleared, the result received outside of the function is empty.
The code for PolyTree::Clear()
void PolyTree::Clear()
{
for (PolyNodes::size_type i = 0; i < AllNodes.size(); ++i)
delete AllNodes[i];
AllNodes.resize(0);
Childs.resize(0);
}
Probably you should follow the pattern of Execute and define your function as:
void MeshHandler::trianglesToPolyTreeUnion(std::vector<Triangle> triangles,ClipperLib::PolyTree &tree)
Assuming you don't want to modify the (obviously badly designed) Clipper library, you can do it like I suggested in my comment:
// Make sure to have this at the top of your header file:
#include <memory>
std::unique_ptr<ClipperLib::PolyTree> MeshHandler::trianglesToPolyTreeUnion(std::vector<Triangle> triangles)
{
// Rest of your code...
std::unique_ptr<ClipperLib::PolyTree> tree(new ClipperLib::PolyTree);
clipper.Execute(ClipperLib::ClipType::ctUnion, *tree);
return tree;
}
Then, when calling your function:
std::unique_ptr<ClipperLib::PolyTree> tree(yourMeshHandler.trianglesToPolyTreeUnion(/*...*/);
// make use of tree...
Still, I would suggest opening a ticket (if there's a bug tracker) or contacting the library's author about this issue.
Is there already a solution for this problem? I am dealing with the same problem.
Still no luck. The polytree outputs only memory adres.
when using : qDebug()<< "child id " << polynode->Childs;
When we have 2 childs, the output in terminal is :
std::vector(0x55f30d2a91b0, 0x55f30d258480)
I hope someone knows how to solve this..
Your problem is in the third line from the bottom of trianglesToPolyTreeUnion. The tree you are creating is created on the stack and is only in scope within the function.
You should dynamically allocate the memory and return a pointer to the tree or make your tree object a class member so it is still within scope once the function returns.
Related
Let's assume I got an abstract class ("Book" in the example below) and some derived classes ("ElectroniBook","CodingBook" in the example below). I also want to keep a vector of books in a third class ("Library") and some maps to find them. Let's also assume that I need to create the "Library" from somewhere else using the "addBook" method and then assign it in the main.
Since Book is abstract I eventually need to delete the "Book" pointers I created and I want to do it in some destructor. Neverthless, whenever I try to use delete i got this error message
Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)
and if I try to replace raw pointers with shared_pointers or unique_pointers I immediately get errors at compile time telling me I'm trying to use pointers that have already been deleted. Note that I'm using C++ 11.
Here's some code just for example :
class Book{
public:
Book(string name, int Npages);
virtual ~Book();
virtual void displayBook() = 0;
private:
string _name;
int _Npages;
}
class ElectronicBook : public Book{
public:
ElectronicBook(string name, int Npages);
~ElectronicBook();
void displayBook() { //do something
};
}
class CodingBook : public Book{
public:
CodingBook(string name, int Npages);
~CodingBook();
void displayBook() { // do something else
};
}
class Library{
public :
Library();
~Library(){
// this doesn't work for me
// for(auto & a : _books)
// delete a;
// _books.clear();
//
//for(int i=0;i<_bookmap.size();++i)
// delete bookmap.at(i);
};
void addCodingBook(string name, int Npages){
CodingBook* cb = new CodingBook(name, Npages);
_books.push_back(cb);
_bookmap[name] = cb;
//should I delete anything here?
};
void addEletronicBook(string name, int Npages){
ElectronicBook* eb = new ElectronicBook(name, Npages);
_books.push_back(eb);
_bookmap[name] = eb;
//should I delete anything here?
};
private :
vector<Book*> _books;
map<string, Book*> bookmap;
}
// separeted function
Library createLibrary(){
Library L;
while(...){
//read books from somewhere(file, input or whatever) and
// addElectronicBook(...)
// addCodingBook(...)
}
return L;
}
int main(){
Library myLibrary = createLibrary();
// do something with Library
}
Since I did several times "new" to add Books, I need to delete them. I tried to do it in the Library destructor like I showed but I got the error mentioned before.
If I understand correctly your issue, you are freeing twice the same memory:
// for(auto & a : _books)
// delete a;
// _books.clear();
//
//for(int i=0;i<_bookmap.size();++i)
// delete bookmap.at(i);
Both _books and bookmap contain pointers that are pointing to the same ares of memory and you are freeing them twice.
When working with raw pointers you have to decide who is the owner of the memory, say, for example _books and who has simply access to the memory but is not responsible for the cleanup.
So, you should:
delete only once, so use only one of the two for loops, say for the sake of argument _books
make sure that the other non-owning structures, say bookmap in our example, never, ever access the memory (i.e. de-reference the pointer) after the deletion
Suggestion: put in the vector unique_ptr so the vector is the owner and put raw pointers in the map to signal that the map is not owning. unique_ptr will take care of cleaning up the memory for you. If you want to be sure, add some print statements or put break points in the destructors if you have a debugger.
I'm trying to create a node class that contains a vector of pointers. Here's my code:
node.h:
#ifndef NODE_H
#define NODE_H
class node
{
public:
vector<node*> next;
void add_arc(node & a)
string some_string;
#endif
node.cpp:
void node::add_arc(node & a)
{
node *b = &a;
next.push_back(b); //only copyies nodes
}
main.cpp:
int main()
{
vector<node> nodes;
node a;
node b;
node c;
a.somestring = "a";
b.somestring = "b";
c.somestring = "c";
a.add_arc(b); //a should point to b
a.add_arc(c); //a should point to c
nodes.push_back(a);
nodes.push_back(b);
nodes.push_back(c);
cout << nodes[0].next.size() << endl; // prints "2", works fine
cout << nodes[0].next[0]->some_string << endl; //empty
}
I thought it would be as easy as just overloading push_back:
void push_back(vertex * pointer)
{
next.push_back(pointer);
}
But I think I really need a copy constructor, or some other method to make this work. How would I go about doing this for a vector of pointers?
Edit: I guess I didn't explain it well. Look at the answers in this question:
Segmentation fault when accessing a pointer's member function in a vector
Making 'a' a reference did not work for me
It works...
Your code generates as expected the correct output (see online demo):
2
b
...However this design is not future proof
However this result is related somehow to luck, because in your code snippet:
the nodes in the nodes vector are copies of the original object including all their pointers
the local objects a, b, c to which these pointers point still exist
However in more complex code, you'd quickly end up with dangling pointers.
Imagine:
Bad example 1: you create a graph, keeping all the nodes directly in a vector of nodes. You then add the first arcs between the nodes. As soon as you'll add a new node to the vector, reallocation might occur and you'd risk to see all your next pointers invalidated.
Bad example 2: you initialise a graph like you did, but in a function called by main. In this case, as soon as you return from this function, all the local nodes get destroyed and the vector's node will point to objects that do no longer exist. UB guaranteed !
How to improve ?
Your design fails to recognize that the nodes all belong to the same graph.
There is a quick and dirty way out: always create the node from the free store, and store them in a vector<node*>.
vector<node*> nodes;
node *a = new node("a"); // Imagine a node constructor
node *b = new node("b");
a->add_arc(b); //change signature, to accept a pointer
nodes.push_back(a);
nodes.push_back(b);
There's a better approach: improve further the previous approach, but use shared_ptr<node*> to make sure that nodes that are no longer referenced (neither by a vector of nodes, nor by an arc) are destroyed automatically.
There's an even better approach: encapsulate the nodes in a class representing a graph. In this case, you could consider using a vector<nodes> and replace the pointers in next, by indexes of the target nodes in the vector. No pointer, but perfect copy of graphs will be much easier. And no more memory management hassle.
class node // just to give the general idea
{
public:
vector<int> next; // not usable without the graph
void add_arc(int a)
string id;
};
class graph {
vector<node> nodes;
public:
void add_node (node a);
void add_arc (string from, string to);
node& operator[] (size_t i);
...
};
I'm trying to implement the Ford Fulkerson Algorithm in C++.
However, I'm having trouble with my find_edge function. When I call this function in my_alg, it chooses the correct edge and then the flow is incremented in my_alg. It chooses the right edge and increment its flow (flow), but when I call the find_edge function again, the flow is not incremented as it should be.
This results in an endless loop of my algorithm. Probably I do something wrong with the pointers. You can see my code below.
//An object of this class represents an edge in the graph.
class Edge
{
private:
//Node *prev;
public:
int flow;
Edge(Node *firstNode, Node *secNode, unsigned inCost) {
orgNode = firstNode;
dstNode = secNode;
bridge_capacity = inCost;
}
Edge() {
flow=0;
}
};
//An object of this class holds a vertex of the graph
class Node
{
public:
Node *prev;
vector<Edge>& getAdjNodeList() {
return adjNodeList;
}
};
Edge *find_edge(Graph *g,Node *from,Node *to) {
vector<Edge> b=from->getAdjNodeList();
for(int i=0;i<b.size();i++) {
if(b[i].getDstNode()==to)
return (&b[i]);
}
return NULL;
}
int my_alg(Graph *as,Node *source,Node *sink){
Edge *find_edge();
int max_flow=0;
while(bfs(as,source,sink)) {
Node *b=as->nodeList[num_isl];
int inc=100000000;
while(b->prev!=NULL) {
Edge *bok=find_edge(as,b->prev,b);
inc=min(inc,bok->get_bridge_capacity()-bok->flow);
b=b->prev;
}
b=as->nodeList[num_isl];
while(b->prev!=NULL){
Edge *bok = find_edge(as,b->prev,b);
bok->flow += inc; // This is the place the flow is incremented
bout << bok->flow; // Here, everything is alright.
bok = find_edge(as,b->prev,b);
cout << bok->flow; // However, this is is not the correct result.
}
max_flow+=inc;
}
return max_flow;
}
I had a more thorough look at your code. To help you track your problems down yourself in the future, I will show you a sample process of finding the error.
If you really can not find the problem by looking at the code, you may want to strip down everything that obfuscates your view on the problem. The reduced code could look like this:
class Edge {
public:
int flow;
};
class Node {
private:
vector<Edge> adjNodeList; // list of outgoing edges for this vertex
public:
vector<Edge> & getAdjNodeList() {
return adjNodeList;
}
void addAdjNode(Node* newAdj) {
adjNodeList.push_back(Edge(newAdj));
}
};
int main() {
Node *node1 = new Node();
Node *node2 = new Node();
node1->addAdjNode(node2);
vector<Edge> t = node1->getAdjNodeList();
vector<Edge> f = node1->getAdjNodeList();
t[0].flow = 11;
cout << t[0] << endl;
cout << f[0] << endl;
}
If you would run this code, you would notice that t[0] and f[0] are not the same. As I just copied the crucial elements of your code, the reason should still be the same.
What is happening here? When calling
vector<Edge> t = node1->getAdjNodeList();
the adjacency list is returned by reference, which should leave you with a reference to the original list - you should be able to change it's elements, shouldn't you? However, when assigning this reference to the newly allocated vector t, the implicit copy constructor is called, thus t will contain a copy (!) of your vector while you wanted to save a reference.
To get around this problem, you could just have done the following:
vector<Edge> & t = node1->getAdjNodeList();
which saves the reference and does not create a new object.
I can only assume why the pointers happened to be identical between calls to the function: The object probably was copied to the same place every time. Furthermore, note that you increased the value of an object that did not exist anymore - the copy was deleted with the end of the find_edge-call.
It took some time to give an answer to your question as you did not track the problem down yourself. If you had given the example above, I bet your solution would have been there within a matter of minutes. You are encouraged to raise your problems here at stack overflow - however, most members will not be willing to work through a lot of code to identify the problem themselves. That means, high quality answers usually require questions that directly come to the point. (The last paragraph was intended to help you in the future, however, it could be reduced without altering the question).
Apart from that, I would strongly encourage you not to use your objects the way you do. By passing everything as references and making all changes outside the object, you essentially bypass the encapsulation that makes object orientated programming that powerful. For example, it would be much wiser (and would not have given you your problem) if you just had added another function increaseFlow(Edge* to, int increment) to your Node and had done everything within the object.
Hope I could help.
Hey..
I'm having trouble with some homework.
We are working on VectorList ( kinda like linked list but with vectors - don't ask why.. )
Anyway I have something like this:
#ifndef VECTORLIST_H
#define VECTORLIST_H
#include <iostream>
#include <vector>
using namespace std;
template< typename NODETYPE >
class VectorList
{
public:
VectorList(); // constructor
~VectorList(); // destructor
void insertAtFront( const NODETYPE & );
void insertAtBack( const NODETYPE & );
bool removeFromFront( NODETYPE & );
bool removeFromBack( NODETYPE & );
bool isEmpty() const;
void print() const;
private:
vector< NODETYPE > *vList; // list data as a vector
};
I need to fill in the functions.. my problem is that I do not understand how
to use STIL when I have *vList.. its a pointer to the first vector element?
// display contents of VectorList
template< typename NODETYPE >
void VectorList< NODETYPE >::print() const
{
// Fill in the missing code
}
My Idea was to use a for loop on the vector and use cout<< vector[i]<< endl;
to print the vector out..
Problem is that I get all sorts of errors and seg faults.
I do not understand how to access the vector in the function,
and how to access its elements.
This is a header file, and in the main we declare an object of VectorList<NODETYPE> IntVector...
So how can I do this?
Any help with understanding of how this *vList plays a role here would help a lot and
I'd probably be able to finish the rest..
Also, for isEmpty(), I assume I can use vList.empty().. but since vList is a pointer..
it doesn't work quite well.
== For the constructor/destructor what can I do?
I know for destructor I should iterate through the vector and use delete on each element.
But shoul
Please explain this to me, I am frustrated =[
my problem is that I do not understand how to use STL when I
have *vList.. its a pointer to the first vector element?
I assume that you are required as part of your homework to use pointer-to-vector instead of a vector itself. As a rule, I never use pointers-to-containers. In fact, the best thing that I discovered in switching from C to C++ was that I could write entire programs with no pointers at all, thanks to STL programming. Unless you are required to use pointer-to-vector, I recommend that you use the vector directly.
Certainly it is easier to use the vector proper than a pointer, but don't worry. Using the pointer isn't too bad.
First, in order to use a pointer-to-something, one must allocate the something. So, in your constructor, invoke new.
vList = new std::vector<NODETYPE>;
Anytime we invoke new, we must have a matching delete somewhere. Since our new is in our constructor, we need to invoke delete in the destructor:
delete vList;
You said:
but since vList is a pointer.. it doesn't work quite well.
Here is where life gets easy. Generally, if p is a pointer to some type, then (*p) is the object to which p points. Here are some examples:
int i = 1;
int *pInt = &i;
i = 4;
(*pInt) = 4;
std::cout << i << " " << (*pInt) << "\n";
std::vector<NODETYPE> v;
std::vector<NODETYPE> *pVector;
v.push_back();
(*pVector).push_back();
it = v.begin();
it = (*pVector).end();
So, invoking members of vList is easy : (*vList).empty().
So, your code might be :
void insertAtFront(const NODETYPE& node) { (*vList).push_front(node); }
There is a short-cut operator -> that makes the above somewhat easier to read:
void insertAtFront(const NODETYPE& node) { vList->push_front(node); }
The expression x->y is more-or-less equivalent (*x).y.
To sum up:
Allocate your vList in your constructor with new. Destroy your vList in your destructor with delete. Invoke members of vList using either (*vList).function() or vList->function().
Good luck, and come back if you have other questions!
P.s. Since you have a non-trivial destructor, you'll need to consider the rule of three.
P.P.s. You said something about iterating the vector in your destructor and deleting each of the objetcs you find there. You would only need to do that if your data type were vector-of-pointers-to-NODETYPE (contrast to what you declared: pointer-to-vector-of-NODETYPE). Until and unless you become completely comfortable with pointers, I recommend that you never store pointers in STL containers.
You should construct your object in the constructor (if you really need using bare pointers): vList = new vector< NODETYPE >();, free memory in the destructor: delete vList;, translate your methods to corresponding methods of the container class. For example, insertAtBack would be implemented as vList->push_back(elem);
I have a method in a static class which tries to convert a binary tree to a list
I'd like to make it recursive but I couldn't
I've implemented some other methods in my class like add(), delete(), find().
Here is the code
class ARB
{
private:
struct BT
{
int data;
BT *l;
BT *r;
};
struct BT *p;
public
ARB();
~ARB();
void del(int n);
void add(int n);
};
void ARB::del(int num)
{
//The code ,don't care about it
};
main()
{
//
BTR T;
T.add(3);
T.add(5);
};
Here is what should we do to transfer the code from binary tree to list.
LLC ARB::changeit()
{ LLC x;
while(this!=NULL)
{
x.add(this->data); //
if(this.l==NULL)
{
x.print(); //To print the elemnts of List
return(x);
}
else
{
x=changeit(this.l);
}
if(this.r!=NULL)
{
x.~LLC();
x=changeit(this.r);
return(x);
}
}
}
The description of the problem is hard to follow but I noticed that you used the keywords this and static, which are generally mutually exclusive.
Any static function pertains to a class, not an object. Static functions can be called using the ARB::myStaticFunction() syntax and do not require an actual ARB object. So, this inside such a function does not refer to any object and is meaningless.
This call is meaningless:
x=changeit(this.l);
Since this refers to the ARB object that has no member called l. The same goes for this code:
this->data
You sometimes do this.data and sometimes this->data so you seem to be confused over the notion of an object pointer. Your ARB has the BT* called p which is the tree root, supposedly. You should start from it.
Also this is obviosly wrong:
x.~LLC();
Don't call the destructor of LLC explicitly!
The general algorithm for recursively placing a binary tree into a list (pseudocode):
tolist(node, list):
if node == NULL:
return
else:
tolist(node.left, list)
list.append_to_end(node.data)
tolist(node.right)
This assumes append_to_end of list is efficient, to make sense (this is achievable with an end pointer in the list). Also, it takes a list as an argument and modifies it. You can easily change it to have an internal recursive method that does that and an external method that creates a list, calls this method, and returns the list.