0

So I have this code:

void blocks(std::string URL, std::string auth)
{
    const char* cstr_url = URL.c_str();
    std::string s = ("Authorization: " + auth);
    const char* auth_header = s.c_str();
    (··· and so on ···)
}

And everything seems fine if we look in the "autos" field in Debug mode:

enter image description here

But if we try to change the code in a way that ("Authorization: " + auth) is a temporary instance of the String class, in order to avoid declaring the s variable (and therefore saving space -at least, that's my purpose-):

void blocks(std::string URL, std::string auth)
{
    const char* cstr_url = URL.c_str();
    const char* auth_header = ("Authorization: " + auth).c_str();
    (··· and so on ···)
}

...what we get in the Debug "autos" field is something quite different (lots of Ý chars): enter image description here

I thought C++ could support these kind of things (which I don't know how are they technically called, I assume "implicit instance" as an original name). I would swear Java could support these "implicit instances" though.

So the actual question is, what's happening in here? Is there any workaround to avoid declaring an s variable?

  • 3
    `const char* auth_header = ("Authorization: " + auth).c_str();` bind `auth_header ` to a temporary that is destroyed at the end of the expression. You have a dangling pointer. – Richard Critten Jul 24 '20 at 21:12
  • What would you do to fix this dangling pointer? @RichardCritten –  Jul 24 '20 at 21:28
  • You have to keep the result of `("Authorization: " + auth)` alive for as least as long as you want to use `auth_header` for – Caleth Jul 24 '20 at 21:33
  • Seems like an XY problem -- why are you using `const char *` and c_str() at all? It pretty much just exists for interacting with legacy C interfaces and should not be used otherwise. – Chris Dodd Jul 24 '20 at 22:01
  • @ChrisDodd I know. The reason is that I use the libcurl library whose strings are C strings, not C++ string objects. –  Jul 24 '20 at 22:03
  • 1
    @ElJaviLuki: in which case you should only call c_str() directly in the arguments to the libcurl calls -- don't create `const char *` tempvars. – Chris Dodd Jul 24 '20 at 22:05
  • @ElJaviLuki -- Just because another API uses C-style strings doesn't mean you have to emulate this in your own code. As stated, you should work purely using `std::string`, and if an API wants a C-style string, then call the function using `string.c_str()`. – PaulMcKenzie Jul 25 '20 at 02:21

1 Answers1

1

The debug build has very kindly thoroughly destroyed the chars that ceased to exist after that statement, rather than leaving them in a state where you might think things were ok.

The C++ name for such things is "rvalue" (and specifically "prvalue"), which denotes the value category of the expression ("Authorization: " + auth). Rvalues are objects that are about to be destroyed.

auth_header is now an invalid pointer, and doing anything with it (besides re-assigning it) has undefined behaviour.

Caleth
  • 52,200
  • 2
  • 44
  • 75