khajvah
khajvah

Reputation: 5090

map/set iterator is not dereferencable C++ map

Please, have a look at my code.

int main () {
    Program* allcommand = new Program;
    allcommand->addCommand("add", new Add);
    allcommand->addCommand("convert", new Convert);
    allcommand->addCommand("exit", new Exit);
    allcommand->addCommand("help", new Help);
    allcommand->addCommand("show", new Show);
    allcommand->addCommand("modify", new Modify);

    std::string input;
    Command* obj;
    while (true) {
        std::cout << "\nCommand >> ";
        std::getline(std::cin, input);
        std::map<std::string, Command*> :: iterator it;
        std::vector<std::string> parsedinput = allcommand->parse(input);

        it = allcommand->getCommands().find(parsedinput[0]);
        obj = it->second;

        obj->start(parsedinput);
        delete obj;
    }

    return 0;
}

It registers commands to a map which holds its command name and pointer to its class. This compiles without problems but when I enter a command, it crashes with "map/set iterator not dereferencable". I am new to maps (few minutes) so please help.

EDIT. Ok I found that the problem is not in main... Here is code of Program class (some of it)

    void Program::addCommand(std::string command1, Command* obj) {
    m_allCommands[command1] = obj;
}

std::map<std::string, Command*> Program::getCommands () {
    return m_allCommands;
}

I think the problem is here, because after i register commands in main, I cannot cout the name of any command (same problem)

Upvotes: 1

Views: 3940

Answers (2)

rectummelancolique
rectummelancolique

Reputation: 2237

std::map<std::string, Command*> Program::getCommands () {
    return m_allCommands;
}

returns a copy of the m_allcommands map. So when you do:

it = allcommand->getCommands().find(parsedinput[0]);

You get an iterator on the temporary object returned by allcommand->getCommands() that gets destroyed when the assignment is done. Therefore it points to nothing.

Change getCommands() to:

std::map<std::string, Command*>& Program::getCommands () {
    return m_allCommands;
}

or even better:

const std::map<std::string, Command*>& Program::getCommands () const {
    return m_allCommands;
}

Upvotes: 3

Salgar
Salgar

Reputation: 7775

After a call to find() you need to check if

if(it == allcommand->getCommands().end()) {
   //Not Found
} else {
   obj = it->second;
   obj->start(parsedinput);
}

Upvotes: 2

Related Questions