std::map< MyClass, std::vector<MyClass> > Segment fault. Oddness - c++

SOLVED:
Thanks figured it out thanks to dominic hamon.
It all boils down to trying to call a function on a kinda null object. It could use parts of the object but not others.
I had no idea that this could even happen.
Question
I have experienced an odd segmentation fault with a
std::map< IntVector3, std::vector<IntVector3> >.
In my MyClass.hpp file I make this a private property:
std::map< IntVector3, std::vector< IntVector3 > > recurData;
In my MyClass.cpp file in the constructor for MyClass i can run
std::vector< IntVector3 > pt;
pt.push_back(IntVector3(1,2,3));
recurData[IntVector3(1,2,3)] = pt;
This runs correctly and i don't get a fault.
Later in the program i call a function in MyClass that does the same thing, altering of recurData. Not in the constructor. This causes a segmentation fault. There is no other change to my knowledge that affects recurData.
The implementable of IntVector3 is:
http://pastebin.com/Hc83xapk
There is a lot of extra operators that i added that are unneeded (>=,<=...).
(I tried to follow the rule of 3)
The only real oddness is the < operator. This uses a std::string to compare. This quick hack should work for all x,y,z if they are under 99.
Thanks for the help, this has been driving me crazy.

Using a string to achieve a comparison function is (a) massively inefficient, and (b) broken. It will not provide you a strict-weak ordering, which is what is required for std::map. In particular, it is not going to be transitive, i.e. if a < b and b < c, it won't necessarily give you that a < c. This is going to totally mess up std::map.
A typical implementation of < would be something like:
bool operator< (const IntVector3 &a, const IntVector3 &b)
{
if (a.z < b.z) { return true; }
if (a.z > b.z) { return false; }
if (a.y < b.y) { return true; }
if (a.y > b.y) { return false; }
return (a.x < b.x);
}

Related

std::sort equal objects with multiple properties

I'm trying to sort a vector of objects so that objects with the same properties are right next to each other. Task is a class that takes and holds 3 pointers to some data somewhere.
vec.push_back(Task(&propertyOne, &propertyTwo, &propertyThree));
If I have a vector full of these, I want to sort them so that any Task that has equal propertyOne, propertyTwo, and propertyThree are put next to each other in the vector. If the two Task objects properties are not equal, it doesn't really matter where they go. Although it would be nice for them to go next to the Task objects that they have the most in common with.
How do I do this? I've tried the obvious (return a.propertyOne == b.propertyOne) but that didn't seem to work at all, and also it only compares the first property.
Best solution is use a tuple<property*, property*, property*> not a Task. This comes with comparison operators defined so you could simply do: vec.push_back(make_tuple(&propertyOne, &propertyTwo, &propertyThree)) for each entry into vec, then to sort just do:
sort(vec.begin(), vec.end())
If Task must be more elaborate than a tuple<property*, property*, property*>, you should define comparison operators for Task:
bool Task::operator< (const Task& rhs) {
return make_tuple(a, b, c) < make_tuple(rhs.a, rhs.b, rhs.c);
}
bool Task::operator== (const Task& rhs) {
return a == rhs.a && b == rhs.b && c == rhs.c;
}
Once these two are defined you can again do:
sort(vec.begin(), vec.end())
Let's task have three properties a, b, c for short. To sort such tasks in correct order you have to do something like this:
std::sort(v.begin(), v.end(), [](const Task& l, const Task& r) {
if (l.a == r.a) {
if (l.b == r.b) {
return l.c < r.c;
}
return l.b < r.b;
}
return l.a < r.a;
});
I'd do it using a simple lambda containing a couple of ternary operators
std::sort(v.begin(), v.end(), [](const Task& l, const Task& r)
{
return (l.a == r.a) ?
((l.b == r.b) ? (l.c < r.c) : (l.b < r.b)) :
(l.a < r.a);
});
This obviously assumes the properties a and b can be compared using ==, and that all three properties can be compared using <.
Alternatively, you might want to supply appropriate specialisations of functionals from <functional> (std::equal_to, std::less, etc) and use those instead.

C++ “invalid comparator” error in operator overload when negating the result

I ran into very strange problem regarding operator overload. The function below works fine outside the if branch. When I attempt to negate the result of comparison I always get “invalid comparator” error.
Negating using ! does not work, same with ternary operator. Why is this happening?
bool operator<(const Team& firstTeam, const Team& secondTeam)
{
if (firstTeam.getId() > 8) {
return !( firstTeam.getId() < secondTeam.getId());
}
return firstTeam.getId() < secondTeam.getId();
}
Suppose there is team a with id 9 and team b with id 7, then b < a (outside of if) and a < b (inside if) are both true
Correct comparator should define strict weak ordering
It's not 100% clear what are you trying to achieve, but the following code will define correct strict weak ordering
bool operator<(const Team& firstTeam, const Team& secondTeam)
{
if (firstTeam.getId() > 8 && secondTeam.getId() > 8) {
return firstTeam.getId() > secondTeam.getId(); // note > instead of <
}
return firstTeam.getId() < secondTeam.getId();
}

Best way to iterate through a for loop, and then iterate through it again backwards?

I found that when writing animations I sometimes run into having to go through a for loop once, then iterate the value down afterwards. This was generally used for jump animations, or disappear then appear again animations.
Here's an example of what I had done -
// Make the sprite slowly disappear
for (int i = 256; i > 0; --i)
{
sprite.opacity(i);
draw();
}
// Make the sprite slowly appear again
for (int i = 0; i < 256; ++i)
{
sprite.opacity(i);
draw();
}
Every time I did this I had a deep feeling that it was too much. What would be a nicer way of going about this? I'm not entirely sure what would be best practice. I imagine I could use reverse_iterator, but I'm also not sure how I would implement it.
Consider the use of <cmath> abs() function:
for( int i = -255; i <= 255; i++)
use( abs( i ) );
You can use the absolute value function abs() defined in <cmath>. It will halve the code written in your case.
for(int i=0; i<512; ++i)
{
sprite.opacity( abs(256-i) );
draw();
}
I believe in the situation you are describing, you have to iterate through the sprites to set the opacity of each sprite. Whether you use a for loop, or a reverse_iterator, the time spent is going to be the same. Any implementation of the reverse_iterator will still have to iterate through each sprite. There might be ways to make it easier to read, but in the end the algorithm will come down to the same. For example, you could take advantage of the stack and call the sprites recursively to increase the opacity and then decrease on the way back out; however, I see no gain in doing so the algorithm time would still end up being the same.
In some cases, you just need to bite the bullet and spend the time doing things in a way that may seem like (or even be) brute force.
That's a great way to iterate through a loop both forward and "in reverse" - one commonly used by C++ programmers.
For your sprite, it appears that the 256 range (you might consider setting a const int RGB_RANGE equal to 256 - or a more appropriate identifier) is all that is needed; however, were the size of your object dynamic, you could also consider using the .size() function (something like an ArrayList or a vector - here is where something like an iterator would be useful):
for (i = 9; i < RGB_RANGE; i++)
{
// CODE
}
The above code being an example of the first const suggestion. Remember, simple code is never a bad thing - it means you are doing something right.
If you don't want to use abs, I'd go with something like :
template<typename Func>
void animate (size_t step_count, Func && f)
{
size_t step;
for (step = step_count ; step > 0 ; --step)
f(step - 1);
for (step = 1 ; step < step_count ; ++step)
f(step);
}
Use case :
animate(256, [](size_t step)
{
sprite.opacity(step);
draw();
});
If you wish to just iterate a range up and down again, you can go the very crazy route and just define a "container" (or range, in boost lingo) that provides iterators (well, technically they are more almost-iterators) which allow you to express exactly what you intend to do:
for(auto i : down_and_up(3)) ::std::cout << i << "\n";
For example should print
3
2
1
0
1
2
Sadly, there is not much support in the standard library for types like this, although boost provides boost::iterator_range, boost::counting_iterator, and boost::join that, in concert with std::reverse_iterator, can provide down_and_up. Writing one yourself if fairly simple (although verbose), as long as you do not completely abuse it:
struct down_and_up
{
size_t from;
down_and_up(size_t const from) : from(from) { }
struct iterator : public ::std::iterator<::std::forward_iterator_tag, size_t> {
size_t cur;
bool down;
iterator(size_t cur, bool down) : cur(cur), down(down) { }
size_t operator*() const { return cur; }
iterator& operator++()
{
if(down)
{
--cur;
if(0 == cur) down = false;
}
else ++cur;
return *this;
}
friend bool operator==(iterator const& lhs, iterator const& rhs) { return lhs.down == rhs.down && lhs.cur == rhs.cur; }
friend bool operator!=(iterator const& lhs, iterator const& rhs) { return lhs.down != rhs.down || lhs.cur != rhs.cur; }
};
iterator begin() const { return iterator{ from, true }; }
iterator end() const { return iterator{ from, false }; }
};
Note: If you wish, you can easily extend it with more container capabilities, like a value_type member typedef, but this definition is enough for the above example.
P.S.: The boost way, for your entertainment:
boost::iterator_range<boost::counting_iterator<size_t>> up(boost::counting_iterator<size_t>(0), boost::counting_iterator<size_t>(3));
boost::iterator_range<std::reverse_iterator<boost::counting_iterator<size_t>>> down(
std::reverse_iterator<boost::counting_iterator<size_t>>(boost::counting_iterator<size_t>(4)),
std::reverse_iterator<boost::counting_iterator<size_t>>(boost::counting_iterator<size_t>(1)));
for(auto i : boost::join(down, up)) ::std::cout << i << "\n";

C++ throwing a std::bad_alloc exception for very small std::vector using std::sort

I'm working on a project in C++ which deals with comma separated data (CSV). What I do is reading the data from a .csv file into a vector of CsvRow objects.
So, today I encountered a really weird std::bad_alloc exceptions being thrown in much more weird situations. Namely, the first test case in which I managed to get a little more time until I get the exception thrown was reading a whole csv file into a vector. The file consists of 500,000 rows and its size is about 70MB. The file was read into memory like a charm, but then after a few seconds into the sorting procedure, the std::bad_alloc gets thrown. It used roughly 67MB of RAM
Note: I'm using boost's flyweights in order to reduce memory consumption.
BUT, this test case was even stranger:
I'm reading a 146KB file with a few hundreds of lines, and this time I got the exception while reading the data into a vector, which is totally ridiculous having a 70MB successfully read previously.
I'm suspecting a memory-leak, but my machine has 8GB of RAM, using 64-bit Windows 8.
I'm using CodeBlocks, and a MinGW 64-bit boost distro.
Any help would be appreciated.
Here is a chunk of code in which the std::bad_alloc is being thrown:
Reading data from a csv file
std::ifstream file(file_name_);
int k=0;
for (CsvIterator it(file); it != CsvIterator(); ++it) {
if(columns_ == 0) {
columns_ = (*it).size();
for (unsigned int i=0; i<columns_; i++) {
distinct_values_.push_back(*new __gnu_cxx::hash_set<std::string,
std::hash<std::string> >());
}
}
for (unsigned int i=0; i<columns_; i++) {
distinct_values_[i].insert((*it)[i]);
}
all_rows_[k]=(*it);
k++;
}
Sorting the vector using a internal struct stored in my class
struct SortRowsStruct
{
CsvSorter* r;
SortRowsStruct(CsvSorter* rr) : r(rr) { };
bool operator() (CsvRow a, CsvRow b)
{
for (unsigned int i=0; i<a.size(); i++) {
if(a[r->sorting_order_[i]] != b[r->sorting_order_[i]]) {
int dir = r->sorting_direction_[i];
switch(dir) {
case 0:
return (a[r->sorting_order_[i]] < b[r->sorting_order_[i]]);
break;
case 1:
return !(a[r->sorting_order_[i]] < b[r- >sorting_order_[i]]);
break;
case 2:
return true;
break;
default:
return true;
}
}
}
return true;
}
};
Then, I'm using std::sort() to sort the vector of CsvRows
SortRowsStruct s(this);
std::sort(all_rows_.begin(), all_rows_.end(), s);
This line looks really suspicious, but I could not figure out an easier way to initialize those hash sets.
distinct_values_.push_back( *new __gnu_cxx::hash_set<std::string,
std::hash<std::string> >() );
Deleting those hash sets in the destructor crashes the program (SIGSEGV)
Oh, and another thing to point out is that I can't use the default 32-bit gdb debugger due to my MinGW being 64-bit. The 32bit gdb is bugged and won't work with MinGW 64.
Edit:
Could the boost::flyweight<std::string> which I use in the CsvRow class cause the problem?
In addition to that, here is a part of the CsvRow class:
private:
std::vector<boost::flyweights::flyweight<std::string> > row_data_;
And the overloaded [] operator on the CsvRow class:
std::string const& CsvRow::operator[](std::size_t index) const
{
boost::flyweights::flyweight<std::string> fly = row_data_[index];
return fly.get();
}
Thanks in advance
EDIT - SOLVED:
So, this question solved my problem, although I didn't even think of it.
Every custom comparator we pass to the std::sort() has to be a strict weak ordering, that is being:
1. Irreflexive
2. Asymmetric
3. Transitive
4. Transitivity of incomparability
More info at :This question and This Wiki article
Actually, I did not follow the first one (irreflexivity), that is, if both of the CsvRow objects are equal, it should not "compare" them and return true as if they were okay, but instead return false.
I solved the whole problem by only changing the default return value when both CsvRow a and CsvRow b are equal.
bool operator() (CsvRow a, CsvRow b)
{
for (unsigned int i=0; i<a.size(); i++) {
if(a[r->sorting_order_[i]] != b[r->sorting_order_[i]]) {
...
...
}
}
return false; //this line does not violate the irreflexivity rule
//return true; //but this one does
}
Thanks to everyone who tried to help.
Remember this solution in case you experience a similar problem. It's pretty tricky.
This:
distinct_values_.push_back( *new __gnu_cxx::hash_set<std::string,
std::hash<std::string> >() );
Looks like you are trying to add one default-constructed element to the vector. There's an easier way:
distinct_values_.resize(distinct_values_.size() + 1);
Apart from being easier to type, and more generic, it's also a lot more correct: we should not be newing anything here, just creating a single value at the end, and we should let the vector construct it rather than copying it in, which might be wasteful.
And of course we should never try to delete these values.

Keeping std::map balanced when using an object as key

I am writing some code where I am storing lots of objects that I want to get back based on set criteria. So to me it made sense to use a map with an object as a key. Where the object would contain the "set criteria".
Here is a simplified example of the kind of objects i am dealing with:
class key
{
int x,y,w,h;
}
class object
{
...
}
std::map<key, object, KeyCompare> m_mapOfObjects;
Quite simple, the first thought was to create a compare functions like this:
struct KeyCompare
{
bool operator()(const key &a, const key &b)
{
return a.x < b.x || a.y < b.y || a.w < b.w || a.h < b.h;
}
}
but then i thought the chances of this returning true are quite high. So I figured this would lead to a very unbalanced tree and therefore slow searching.
My main worry is that as I understand it, std::map uses that one function in this way:
if( keyCompare(a,b) )
{
//left side
}
else if (keyCompare(b,a))
{
//right side
}
else
{
//equal
}
So i can't just use a.x < b.x, because then anything with the same x would be considered equal, which is not what i want. I would not mind it ordering it in this way but its the "equal" bit i just can't seem to solve without making it unbalanced.
I figure multiplying them all together is a no no for obvious reasons.
So the only solution i could come up with was to create a "UID" base on the info:
typedef long unsigned int UIDType;
class key
{
private:
UIDType combine(const UIDType a, const UIDType b)
{
UIDType times = 1;
while (times <= b)
times *= 10;
return (a*times) + b;
}
void AddToUID(UIDType number)
{
if(number < m_UID)
{
m_UID = combine(number, m_UID);
}
else
{
m_UID = combine(m_UID, number);
}
}
UIDType UID;
public:
int x,y,w,h;
key()
{
AddToUID(x);
AddToUID(y);
AddToUID(w);
AddToUID(h);
}
}
struct KeyCompare
{
bool operator()(const key &a, const key &b)
{
return a.UID < b.UID;
}
}
But not only does that feel a little hacky, "long unsigned int" isn't big enough to hold the potential numbers. I could put it in a string, but speed is an issue here and I assumed an std::string < is expensive. Overall though the smaller i can make this object the better.
I was wondering if anyone has any suggestions for how to do this better. Perhaps i need to use something other then a std::map or perhaps there is another overload. Or perhaps there is something glaringly obvious that i'm missing here. I really feel like i'm over-complicating this, perhaps im really barking up the wrong tree with a map.
As i was writing this it occurs to me that divide is another way to get a "unique" number but that could also equal very large numbers
All you need is to implement a strict weak ordering, which you can easily achieve using std::tie, which has a less than comparison operator< which performs a lexicographical comparison:
#include <tuple>
struct KeyCompare
{
bool operator()(const key& a, const key& b) const
{
return std::tie(a.x, a.y, a.w, a.h) < std::tie(b.x, b.y, b.w, b.h);
}
}
If you do not have the required C++11 support, you can use std::tr1::tie from <tr1/tuple> or equivalent versions from the boost libraries.
I feel juanchopanza has a very good solution, for those who do not have C++11 support or boost libraries
I found a very simple solution on:
What's the simplest way of defining lexicographic comparison for elements of a class?
This solution works for my particular problem a little better then tuple would (as i also have an array of values that i would like to consider). But I would highly recommend considering tuple in future, as will I.
struct keyCompare
{
bool operator()(const key &a, const key&b)
{
if(a.x != b.x) return a.x < b.x;
if(a.y != b.y) return a.y < b.y;
if(a.w != b.w) return a.w < b.w;
if(a.h != b.h) return a.h < b.h;
return false; //they must be equal
}
}
thanks to juanchopanza for his answer and to anyone else who had a look in