1

I'm writing some code for a game, and I'm attempting to write a helper function to return a string inside an object:

const char* getGhostName(GhostAI* ghostAI)
{
    if (ghostAI) {
        GhostInfo* ghostInfo = getGhostInfo(ghostAI);
        const auto ghostName = ghostInfo->fields.u0A6Du0A67u0A74u0A71u0A71u0A66u0A65u0A68u0A74u0A6Au0A6F.u0A65u0A66u0A6Eu0A67u0A69u0A74u0A69u0A65u0A74u0A6Fu0A67;
        const char* name = il2cppi_to_string(ghostName).c_str();
        return name;
    }
    return "UNKNOWN";
}

And here is the il2cppi_to_string functions:

std::string il2cppi_to_string(Il2CppString* str) {
    std::u16string u16(reinterpret_cast<const char16_t*>(str->chars));
    return std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>{}.to_bytes(u16);
}

std::string il2cppi_to_string(app::String* str) {
    return il2cppi_to_string(reinterpret_cast<Il2CppString*>(str));
}

When I call getGhostName, I end up with an empty string. Now I did get a warning from ReSharper which says:

Object backing the pointer will be destroyed at the end of the full-expression.

This is appearing on the following line inside getGhostName when calling il2cppi_to_string:

const char* name = il2cppi_to_string(ghostName).c_str();

I'm not entirely sure what this means or how I can modify the code to fix it. I absolutely hate working with strings in C++.

ThePerplexedOne
  • 2,920
  • 15
  • 30
  • 2
    Why not just keep using actual `std::string`s instead of trying to juggle `char` pointers? – Quentin Mar 20 '22 at 20:09
  • 3
    You are calling `c_str` on a _temporary_ `std::string` object that will be destroyed before your `return` statement. – jkb Mar 20 '22 at 20:09
  • 1
    "I absolutely hate working with strings in C++." -- I'd say you just need to read a tutorial on C++ strings. You hate it because you're trying to fight a system that you don't understand. – Ulrich Eckhardt Mar 20 '22 at 20:13
  • 2
    "I absolutely hate working with strings in C++." -- Yet you decided to use `const char *` instead of staying with the much-easier-to-use `std::string`. You sabotaged yourself by using `const char *`. – PaulMcKenzie Mar 20 '22 at 20:21
  • Does this answer your question? [Why does calling std::string.c\_str() on a function that returns a string not work?](https://stackoverflow.com/questions/35980664/why-does-calling-stdstring-c-str-on-a-function-that-returns-a-string-not-wor) – JaMiT Mar 20 '22 at 20:23
  • The unofficial rule of thumb is to use `std::string` throughout your code, and only resort to `c_str()` when you are calling a legacy or API function that only allows `const char *` as parameters. Don't (as I mentioned in the previous comment) sabotage yourself by introducing `const char *` on purpose. – PaulMcKenzie Mar 20 '22 at 20:27
  • *"I absolutely hate working with strings in C++."* -- the term "string" can refer to two different beasts in C++ -- `std::string` and null-terminated C-style strings (using the types `char*` and `const char*`). My personal ranking for ease-of-use might be: 1) `std::string`; 2) C-style; 3) start working with C-style, then switch to working with `std::string`; 4) start working with `std::string`, then switch to working with C-style. (Some days I might swap #2 and #3.) You have chosen to use #4. Generalizing your experience with the hardest case to all cases is not exactly a fair assessment. – JaMiT Mar 20 '22 at 20:38

1 Answers1

7

il2cppi_to_string() returns a temporary std::string, which will be destroyed at the end of the expression that calls il2cppi_to_string(). You are obtaining a const char* pointer to the data of that temporary std::string, which is what ReSharper is warning you about. Since the temporary std::string is destroyed before the return, that means getGhostName() is returning a dangling pointer to invalid memory.

To fix this, change getGhostName() to return a std::string instead of a const char*:

std::string getGhostName(GhostAI* ghostAI)
{
    if (ghostAI) {
        GhostInfo* ghostInfo = getGhostInfo(ghostAI);
        const auto ghostName = ghostInfo->fields.u0A6Du0A67u0A74u0A71u0A71u0A66u0A65u0A68u0A74u0A6Au0A6F.u0A65u0A66u0A6Eu0A67u0A69u0A74u0A69u0A65u0A74u0A6Fu0A67;
        return il2cppi_to_string(ghostName);
    }
    return "UNKNOWN";
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770