-1

I have a weird problem. I have a map in C++ defined like this as private in a class.

std::map<const char *, GameObject *> GameObjects;

I have a function that adds pairs to the map.

void myClass::Add(const char *name, GameObject *object)
{
    GameObjects.insert(std::make_pair(name, object));
}

It works fine if I add pairs like this.

m_myClass.Add("Example", new GameObject());

Now, the problem is in the Instantiate function, declared like this.

void myClass::Instantiate(GameObject *object)
{
    char *name = (char *)malloc(strlen("New Object ") + 12);                                  // New Object xxxxxxxxxxxx    x -> digit
    memset(name, 0, strlen("New Object ") + 12);                                              // clear
    strcpy(name, "New Object ");                                                              // copy the first part
    strcpy(name + strlen("New Object "), std::to_string(newObjs++).c_str()); // copy the number part
    printf("Creating %s", name);
    Add(name, object);                                                                         // add it to our map
}

If I iterate over every item from the map, the pair appears to exist and works indexing it but when I index it manually (GameObjects["pairName"]) the program crashes with a segmentation fault message. Also GameObjects.contains("pairName") returns false even if I added the pair with that name.

I use GCC 11.2.0 on Ubuntu with the C++20 standard enabled.

Moldytzu
  • 76
  • 4
  • 6
    Use `std::string` instead of `const char*`. (That solves multiple issues (comparison, and memory)). – Jarod42 Feb 02 '22 at 11:51
  • 1
    Whatever the bug is in your code, try rewriting it. malloc shouldn't be in C++ code (new/delete aren't even recommended). The ownership of the string pointer is unclear (who will delete it? the map?). Just have the map contain std::string and make clear who owns what. e.g. make the pointer to GameObject a std::unique_ptr or something. Check out https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines for anything related to pointers/new/delete etc. – Pepijn Kramer Feb 02 '22 at 11:52
  • thanks you very much for the advice – Moldytzu Feb 02 '22 at 12:04

1 Answers1

1

A string literal has a different pointer value to a return value of malloc. The map will do lookup with std::less<const char *> which compares pointer values, it does not compare text.

Use std::string, and don't use malloc or owning raw pointers.

std::map<std::string, std::unique_ptr<GameObject>> GameObjects;

void myClass::Add(std::string name, std::unique_ptr<GameObject> object)
{
    GameObjects.emplace(std::move(name), std::move(object));
}

void myClass::Instantiate(std::unique_ptr<GameObject> object)
{
    std::string name{ "New Object " };
    name += std::to_string(newObjs++)
    std::cout << "Creating " << name;
    Add(std::move(name), std::move(object));                                                                         
}
Caleth
  • 52,200
  • 2
  • 44
  • 75
  • what's the role of std::move in there? – Moldytzu Feb 02 '22 at 12:02
  • 2
    @Moldytzu, the role of prompting you to get a book on modern C++. Given the knowledge of C++ that is understood from your question, answering your question about `std::move` means going off topic entirely. [This](https://stackoverflow.com/questions/9671749/whats-the-difference-between-stdmove-and-stdforward/65446786#65446786) is an explanation of what `std::move` is, together with its friend `std::forward`. If you set _understanding that answer_ as your target, you'll learn a lot. Whatever the time it takes. – Enlico Feb 02 '22 at 12:04
  • @Moldytzu It converts lvalue to rvalue. Its not possible to answer you in one line. But I would recommend you to give a read to `Move Semantics`. – foragerDev Feb 02 '22 at 12:04