Using own class as key in map causes segmentation fault

N

nw

Hi,

I'm trying to use my own class as a map key. However something strange
seems to be happening to the map which causes my program to segfault.
I'm at a loss as to what this might be. Can anyone help?

The complete example below segfaults for me under g++ 4.1.2. Using a
debugger it seems that one of the MultiDimKey objects the map is
holding becomes corrupt.

#include <vector>
#include <map>
#include <string>
#include <iostream>

using namespace std;

class MultiDimKey {
public:

MultiDimKey() : keys() {
}

MultiDimKey(const vector<string> keys_in) : keys(keys_in) {
}

bool operator<(const MultiDimKey &other) const {

const vector<string> other_keys = other.keys;

for(size_t n=0;n<keys.size();n++) {
if(keys[n] < other_keys[n]) return true;
}

return false;
}

vector<string> keys;
};

int main() {

map<MultiDimKey,int> test;

vector<string> s1;
s1.push_back("3");
s1.push_back("6");
MultiDimKey k1(s1);
test[k1]++;

vector<string> s2;
s2.push_back("5");
s2.push_back("3");
MultiDimKey k2(s2);
test[k2]++;

vector<string> s3;
s3.push_back("6");
s3.push_back("2");
MultiDimKey k3(s3);
test[k3]++;

vector<string> s4;
s4.push_back("1");
s4.push_back("2");
MultiDimKey k4(s4);
test[k4]++;
}
 
A

Alf P. Steinbach

* nw:
Hi,

I'm trying to use my own class as a map key. However something strange
seems to be happening to the map which causes my program to segfault.
I'm at a loss as to what this might be. Can anyone help?

The complete example below segfaults for me under g++ 4.1.2. Using a
debugger it seems that one of the MultiDimKey objects the map is
holding becomes corrupt.

#include <vector>
#include <map>
#include <string>
#include <iostream>

using namespace std;

class MultiDimKey {
public:

MultiDimKey() : keys() {
}

MultiDimKey(const vector<string> keys_in) : keys(keys_in) {
}

bool operator<(const MultiDimKey &other) const {

const vector<string> other_keys = other.keys;

for(size_t n=0;n<keys.size();n++) {
if(keys[n] < other_keys[n]) return true;
}

By this criterion ["3","6"] < ["5","3"] and ["5","3"] < ["3","6"].

std::map will have a really hard time ordering those keys...

return false;
}

vector<string> keys;
};

Cheers & hth.,

- Alf
 
J

Jorgen Grahn

Hi,

I'm trying to use my own class as a map key. However something strange
seems to be happening to the map which causes my program to segfault.
I'm at a loss as to what this might be. Can anyone help? ....

bool operator<(const MultiDimKey &other) const {

const vector<string> other_keys = other.keys;

Not a good place to copy a whole vector<string>, if you want an
efficient map! (It also doesn't simplify the code or even save
any typing.)
for(size_t n=0;n<keys.size();n++) {
if(keys[n] < other_keys[n]) return true;
}

return false;
}

/Jorgen
 
A

AnonMail2005

I'm trying to use my own class as a map key. However something strange
seems to be happening to the map which causes my program to segfault.
I'm at a loss as to what this might be. Can anyone help?
...

  bool operator<(const MultiDimKey &other) const {
    const vector<string> other_keys = other.keys;

Not a good place to copy a whole vector<string>, if you want an
efficient map!  (It also doesn't simplify the code or even save
any typing.)
    for(size_t n=0;n<keys.size();n++) {
      if(keys[n] < other_keys[n]) return true;
    }
    return false;
  }

/Jorgen

There is also a copy of the entire vector in the constructor!!!

HTH
 
V

Vladimir Jovic

There is also a copy of the entire vector in the constructor!!!

No, there isn't. That is the copy constructor that is copying the vector
(which it should)
 
M

Michael Doubez

* nw:
I'm trying to use my own class as a map key. However something strange
seems to be happening to the map which causes my program to segfault.
I'm at a loss as to what this might be. Can anyone help? {snip]
  bool operator<(const MultiDimKey &other) const {
    const vector<string> other_keys = other.keys;
    for(size_t n=0;n<keys.size();n++) {
      if(keys[n] < other_keys[n]) return true;
    }

By this criterion ["3","6"] < ["5","3"] and ["5","3"] < ["3","6"].

std::map will have a really hard time ordering those keys...

And if other.keys.size() < keys.size(), there is UB (and certainly a
segfault).
[snip]
 
A

AnonMail2005

No, there isn't. That is the copy constructor that is copying the vector
(which it should)

There are *two* copies - only one is needed. If you notice, the
argument to the copy constructor is passed by *value* which makes an
extra (unneeded) copy. After that copy, there's another "copy" which
initializes the data member.

HTH
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top