Setting a data breakpoint on an element of a std::map - c++

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.

Related

Assertion failure: list iterator not incrementable (not in a loop)

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.

Does any built in ARRAY function in VC++ 2010?

For example, I have a 10 elements array called 'R'.
I have use 3 of that elements. Can VC++ tell me that which elements are empty and the corresponding index numbers? I googled, but I could not find an answer. (maybe I don't have a good keywords). Please help thanks
you simply could reserve a special value that marks an element as unused. initialize your your array elements with that value and reset the element to that value when it's not used any longer. the way vc++ "tells" you that the elements are unused would then be via the debugger that shows you the reserved value for the unused elements or make a little wrapper class for the array with a function returning the index so there would be not as much oberhead as you have using a template class or stuff like that

Google's dense_hash_map crashing in set_empty_key() function

I am trying to use google dense_hash_map to store key value data instead of std:map.
When I tested with (int, int ) pair, I set the set_empty_key(mymap, -2) and it worked.
But, now when I use it with my (hash, value) pair, I set the set_empty_key (mymap -2) or set_empty_key(mymap, some_random_hash), in both the cases my program crashes in set_empty_key();.
Anyone can guide me with this? How can I fix this crash?
Thanks.
I don't know the exact reason of crash you've got, but, based on your description I see at least two potential mistakes.
First. Check that both key_type and data_type types are POD types and don't contain pointers to itself. More specifically (original):
Both key_type and data_type must be
plain old data. In addition, there should
be no data structures that point
directly into parts of key or value,
including the key or value itself (for
instance, you cannot have a value like
struct {int a = 1, *b = &a}. This is
because dense_hash_map uses malloc()
and free() to allocate space for the
key and value, and memmove() to
reorganize the key and value in
memory.
Second. Concerning using dense_hash_map. You need to set up some special "empty" key value which will never be used for real elements stored in your collection. Moreover if you are going to use erase() you need to specify special key for deleted items which also will never be used as key for real stored items.
That is perfectly described here:
dense_hash_map requires you call
set_empty_key() immediately after
constructing the hash-map, and before
calling any other dense_hash_map
method. (This is the largest
difference between the dense_hash_map
API and other hash-map APIs. See
implementation.html for why this is
necessary.) The argument to
set_empty_key() should be a key-value
that is never used for legitimate
hash-map entries. If you have no such
key value, you will be unable to use
dense_hash_map. It is an error to call
insert() with an item whose key is the
"empty key." dense_hash_map also
requires you call set_deleted_key()
before calling erase(). The argument
to set_deleted_key() should be a
key-value that is never used for
legitimate hash-map entries. It must
be different from the key-value used
for set_empty_key(). It is an error to
call erase() without first calling
set_deleted_key(), and it is also an
error to call insert() with an item
whose key is the "deleted key."

what happens when you modify an element of an std::set?

If I change an element of an std::set, for example, through an iterator, I know it is not "reinserted" or "resorted", but is there any mention of if it triggers undefined behavior? For example, I would imagine insertions would screw up. Is there any mention of specifically what happens?
You should not edit the values stored in the set directly. I copied this from MSDN documentation which is somewhat authoritative:
The STL container class set is used
for the storage and retrieval of data
from a collection in which the values
of the elements contained are unique
and serve as the key values according
to which the data is automatically
ordered. The value of an element in a
set may not be changed directly.
Instead, you must delete old values
and insert elements with new values.
Why this is is pretty easy to understand. The set implementation will have no way of knowing you have modified the value behind its back. The normal implementation is a red-black tree. Having changed the value, the position in the tree for that instance will be wrong. You would expect to see all manner of wrong behaviour, such as exists queries returning the wrong result on account of the search going down the wrong branch of the tree.
The precise answer is platform dependant but as a general rule, a "key" (the stuff you put in a set or the first type of a map) is suppose to be "immutable". To put it simply, that should not be modified, and there is no such thing as automatic re-insertion.
More precisely, the member variables used for to compare the key must not be modified.
Windows vc compiler is quite flexible (tested with VC8) and this code compile:
// creation
std::set<int> toto;
toto.insert(4);
toto.insert(40);
toto.insert(25);
// bad modif
(*toto.begin())=100;
// output
for(std::set<int>::iterator it = toto.begin(); it != toto.end(); ++it)
{
std::cout<<*it<<" ";
}
std::cout<<std::endl;
The output is 100 25 40, which is obviously not sorted... Bad...
Still, such behavior is useful when you want to modify data not participating in the operator <. But you better know what you're doing: that's the price you get for being too flexible.
Some might prefer gcc behavior (tested with 3.4.4) which gives the error "assignment of read-only location". You can work around it with a const_cast:
const_cast<int&>(*toto.begin())=100;
That's now compiling on gcc as well, same output: 100 25 40.
But at least, doing so will probably makes you wonder what's happening, then go to stack overflow and see this thread :-)
You cannot do this; they are const. There exists no method by which the set can detect you making a change to the internal element, and as a result you cannot do so. Instead, you have to remove and reinsert the element. If you are using elements that are expensive to copy, you may have to switch to using pointers and custom comparators (or switch to a C++1x compiler that supports rvalue references, which would make things a whole lot nicer).

"Shallow" display of STL containers in Visual Studio debug mode?

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.