I hit a wall while debuging my C++ class. It's a graph of sorts, something like this:
class Graph {
class Node {
std::map<int, Node>::iterator _neighbors[4];
};
std::map<int, Node> _map;
};
Basically, each node keeps track of exactly 4 neighbors by storing iterators to them in the containing class' map.
The problem is that when I go to display the contents of _map in VS2008 during debugging, I get something like this:
- _map
- [0]
first
- second
- _neighbors
- _ptr
first
- second
- _neighbors
- _ptr
first
- second
- _neighbors
...
Apparently, instead of listing the 4 neighbors of the Node with index 0 in the map, it lists its first neighbor, then the first neighbor's first neighbor, then its first neighbor and so on ad infinity. Also, at no point does _neighbors appear as an array, even though it is declared as such.
I found an add-on called VSEDebug that supposedly has enhanced STL display, but it's for VS2k3 and I couldn't get it to work in 2k8 (neither the binaries, nor compiling it myself).
The immediate window isn't much help either, as trying to call _map.operator[] returns with CXX0058: Error: overloaded operator not found.
Any ideas how I can get a meaningful display of the contents of my map? Note that I'm fairly new to VS as a whole, so I'll probably need detailed instructions. :)
You can type the name of the symbol in the command window - immediate window and start following its member pointers. For example, if you debug a std::vector named v and want to access its element at position 2, type
*(v._Myfirst + 2)
Of course, the member _Myfirst depends on the implementation. But I think you get the idea. (visual studio has some problemas resolvindo overloads of the operators)
You can try your hand at writing a custom visualizer if you like, however you might end up duplicating functionality that already exists somewhat. Here's an article that goes over the basics:
http://www.virtualdub.org/blog/pivot/entry.php?id=120
If you just want to view all your array elements you can type "_map[0].second._neighbors,4" in the quick watch window to view it as an array of four, but this isn't exactly the fastest thing in the world.
Related
First off, good morning/day/evening and thank you to whoever is taking their time to read this.
The Setup:
In my code I have two different classes: ColObj and QuadNode (that is, the 'collision object' and a node in a quad tree used to check for proximity of objects. I know there are probably libraries out there for this, but I need to write my own system, so they would be of no use here). Things work like this: When a ColObj object is created, it is added into an appropriate QuadNode (the node has a std::list of pointers to ColObj), so that the node can inform it when it collides with something; the ColObj object also receives a pointer to the node that's holding it and a list iterator to the list iterator containing its address so when it's out of the node's bounds or gets destroyed it can 'leave' it, and clean up the node, that is, remove and reference to itself from the node. I made it like this because in a lot of cases it's going to be a frequent operation and I want it to be in constant time.
The Code:
This is the method used to 'attach' a ColObj to a QuadNode. I suspect the problem is not in here.
void QuadNode::obj_add(ColObj *obj) {
std::cout<<"QuadNode at depth ("<<depth<<") received new ColObj.\n";
objects.push_back(obj);
obj->holder = this;
obj->my_iter = std::prev( objects.end() );
if ((int)objects.size() > MAX_OBJECTS && depth < MAX_DEPTH) split();
}
This is the QuadNode method that a ColObj uses to clean up the node. Here is where the problem occures for some reason.
void QuadNode::obj_list_erase(std::list<ColObj*>::iterator iter) {
std::list<ColObj*>::iterator iter2 = objects.begin();
objects.erase(iter);
}
The first line in this method is simply to provide additional information for debugging and will be removed afterwards.
The Error:
The strangest part is that, for the most part, the code works fine. Then at one point, randomly, it throws an assertion failure, saying that a "list iterator is not incrementable". That's the first strange thing, I'm not trying to increment it anywhere in my code (though I know that std::list::erase returns the following iterator, but I never attempt this operation on an invalid or "past-the-last" iterator).
Anyway, Visual Studio offers to fire up the debugger and put a break point in the code, so naturally I agree. So here's the weirdest part:
Local and auto variables, debugger screenshot
(I can't embed an image since I'm new here, so it is what it is).
So, unless I'm gravely mistaken here, it's telling me that the passed iterator is equal to be beginning iterator of the list, that its element is still present in the list and corresponds to the first (or rather zero-th) element of the list. And yet, the erase() method fails.
For what it's worth, I've noticed that every single time the program breaks, the passed iterator points to the zero-th element of the list, though I can confirm that the method usually works even when there's only one element in the list.
Additional info and conclusion:
I'm not manually incrementing the iterator anywhere else in the code (which is pretty small and simple anyway).
The IDE I'm using is Visual Studio Community 2015, but I don't know the compiler version. (Microsoft and their naming schemes...)
I tried finding another thread about this on SO but every one I checked was about wrongly placed i++ in list iterations, so sorry if this is a duplicate thread.
I'm completely confused by this problem, because usually between the excellent debugger, std::cout and browsing SO I somehow fix the issue, but this time around nothing useful is coming up, so any advice or suggestion would be very welcome.
Edit:
One thing I have tried "just 'cause" editing the QuadNode::obj_list_erase method so that it compares the passed iterator with the first iterator of its list (objects.begin()) and if they're equal use objects.pop() to remove it, else erase it normally. It didn't work, saying that the iterators weren't compatible, whatever that means...
After finding out that I cannot even compare the passed iterator with any other iterator from the list that was supposed to be holding it (I was getting Assertion failure: iterators not compatible), I searched SO for more info on what it means, and... Andrew Kashpur was right. I did manage to invalidate an iterator by removing the pointed element from the list and putting it back immediately, but without updating the iterator.
Moral of the story: An iterator can seem to point to a "correct" memory location, it may even point to the same address as some valid iterator does, but that does not make it valid or compatible.
currently I am trying to solve two problems when working with iterators.
1 When using something like
forAllIter(PtrDictionary<phaseModel>, phases_, iter)
{
phaseModel& phase = iter();
.
.
.
}
is it possible to get the actual position/index of iterator "iter" (which pointer is the iterator refering to at the moment)?
I know that for the vector class I could use something like described in the following link
What is the most effective way to get the index of an iterator of an std::vector?
but unfortunately the class "PtrDictionary" which I have to use does not offer a method "begin()". Furthermore "PtrDictionary" is basically of type "intrusive doubly linked list".
2
Old Question:
If I define a dictionary like
const dictionary& subDict_Droplets;
subDict_Droplets = properties.subDict("currentValue");
Can I create an iterator for the dictionary, set this iterator to a
specific position of the dictionary (the position I would get from the
first iterator if possible -> see code snippet 1) and get the content
of the dictionary at that position?
I have read the following thread
how to get iterator to a particular position of a vector
but again class "dictionary" does not have any method "begin()".
Edit/New: I have used now a list (which is of "type" vector) like
const List<dimensionedScalar> List_Droplets;
List_Droplets = properties.subDict("currentValue");
The elements of the vector should be accessable like an array as far as I have read :).
However, the type of the object phases_ which is of type PtrDictionary<phaseModel> (parents: DictionaryBase< IDLListType, T > and parent of this: IDLListType) which is mentioned in question 1 I can t change.
Any hints, ideas or code solutions are welcome :)
greetings streight
Sometimes an iterator corresponds to an index that can easily be found, for example a vector iterator. Here you use distance(vector.begin(), iter);
Sometimes an iterator corresponds to an index that cannot be easily found, for example a list iterator. Here you have to start at begin() and work through, counting as you go. distance() will do this if needed but its obviously a lot slower.
Sometimes the idea of an 'index' does not really apply - I think an unsorted map might be a good example of this. distance will still return a value but it doesn't mean much I think. It might even be implementation dependent - I would have to look that up.
I'm writing simple class for undirected graph's representation. Within my class I use adjacency list for graph representation. I would like to add API method, which returns link to some iterable substance, containing vertexes, adjacent to given vertex.
I have the following idea about this method. First - create dynamically allocated std::vector and handle it with shared_ptr. Second - fill vector with proper vertexes numbers and return the link to this vector. So it's prototype looks like:
const std::vector<int>& adjacent(int vertex);
Is it a good idea? Can I do better?
Regards,
Anton
The idea may work, but i strongly recommend you against it. It will be very error prone, and this function definition will look buggy to many other programmers who look at it.
I'd recommend you return vector by value, and do not think about this kind of optimizations until you come to the point where you really need them ( ie - your app is slow, and you are perfectly sure this is the bottleneck ).
If you want to avoid vector copying you can pass vector to this function by reference, so that it will be filled inside.
I have a std::map which is a private member of a class. One of it's values is being changed (when it shouldn't) and I can't figure out where. Once the map is assembled, the element in question is always going to be the last, due to the nature of the keys being used.
I'm trying to set a data breakpoint on the last element (the sixth one to be precise) in Visual Studio 2010 but am having no luck. I've looked through the header of both map and xtree (its base) and can't find a suitable member to use.
Does anyone know how to set a data breakpoint on the value of an element in a std::map?
You should be able to use the debugger to browse through the map to the actual .second data member, and then tack an & in front of the expression it generated. Then put that address into the data breakpoint and see if you have better luck.
[SOLVED]
So I decided to try and create a sorted doubly linked skip list...
I'm pretty sure I have a good grasp of how it works. When you insert x the program searches the base list for the appropriate place to put x (since it is sorted), (conceptually) flips a coin, and if the "coin" lands on a then that element is added to the list above it(or a new list is created with element in it), linked to the element below it, and the coin is flipped again, etc. If the "coin" lands on b at anytime then the insertion is over. You must also have a -infinite stored in every list as the starting point so that it isn't possible to insert a value that is less than the starting point (meaning that it could never be found.)
To search for x, you start at the "top-left" (highest list lowest value) and "move right" to the next element. If the value is less than x than you continue to the next element, etc. until you have "gone too far" and the value is greater than x. In this case you go back to the last element and move down a level, continuing this chain until you either find x or x is never found.
To delete x you simply search x and delete it every time it comes up in the lists.
For now, I'm simply going to make a skip list that stores numbers. I don't think there is anything in the STL that can assist me, so I will need to create a class List that holds an integer value and has member functions, search, delete, and insert.
The problem I'm having is dealing with links. I'm pretty sure I could create a class to handle the "horizontal" links with a pointer to the previous element and the element in front, but I'm not sure how to deal with the "vertical" links (point to corresponding element in other list?)
If any of my logic is flawed please tell me, but my main questions are:
How to deal with vertical links and whether my link idea is correct
Now that I read my class List idea I'm thinking that a List should hold a vector of integers rather than a single integer. In fact I'm pretty positive, but would just like some validation.
I'm assuming the coin flip would simply call int function where rand()%2 returns a value of 0 or 1 and if it's 0 then a the value "levels up" and if it's 0 then the insert is over. Is this incorrect?
How to store a value similar to -infinite?
Edit: I've started writing some code and am considering how to handle the List constructor....I'm guessing that on its construction, the "-infinite" value should be stored in the vectorname[0] element and I can just call insert on it after its creation to put the x in the appropriate place.
http://msdn.microsoft.com/en-us/library/ms379573(VS.80).aspx#datastructures20_4_topic4
http://igoro.com/archive/skip-lists-are-fascinating/
The above skip lists are implemented in C#, but can work out a c++ implementation using that code.
Just store 2 pointers. One called above, and one called below in your node class.
Not sure what you mean.
According to wikipedia you can also do a geometric distribution. I'm not sure if the type of distribution matters for totally random access, but it obviously matters if you know your access pattern.
I am unsure of what you mean by this. You can represent something like that with floating point numbers.
You're making "vertical" and "horizontal" too complicated. They are all just pointers. The little boxes you draw on paper with lines on them are just to help visualize something when thinking about them. You could call a pointer "elephant" and it would go to the next node if you wanted it to.
eg. a "next" and "prev" pointer are the exact same as a "above"/"below" pointer.
Anyway, good luck with your homework. I got the same homework once in my data structures class.