Garbled outcome from Cling


ROOT Version: 6.16.00
Platform: Ubuntu 20.04 LTS
Compiler: gcc 9.3.0


when I tried to extract a sub-string from a string, I got some strange and inconsistent result, I don’t know why. Can someone help me, thank you.

root [0] string input("asym_usl.mean")
(std::string &) "asym_usl.mean"
root [1] int idx = input.find('.')
(int) 8
root [2] const char *a = input.substr(0, idx).c_str()
(const char *) "\x1e"
root [3] a
(const char *) "\xb0\x11\xe3" "E\x07V"
root [4] a
(const char *) "\x80\x85\xe9" "E\x07V"
root [5] a
(const char *) "\x10\xd4\xe9" "E\x07V"
root [6] a
(const char *) "\x90\xf9\xe9" "E\x07V"
root [7] a
(const char *) "\xc0\xc6\xe8" "E\x07V"

Hello,

The problem is C++ related, in const char *a = input.substr(0, idx).c_str() you are taking the value of a temporary. The value of the c_str() is undefined on the next line.

You could do instead

string a = input.substr(0, idx)

Cheers,
Jakob

Hi, Jakob:

Thank you for your answer, one further question is if I write those lines in a script and then run the script with root, I can get the correct answer. What causes the difference?

Best

Now that you mention it, the result of c_str() should actually remain valid until you destroy or modify the string (my “temporary” explanation was wrong, I think). Which would explain why it works in the script but not in the prompt. So apparently there is something more ongoing, cling related. @vvassilev can you explain the result?

The value printing actually captures the value, and indeed: at the time it’s printed the value is gone. I’d be happy to discuss whether / how that can be improved! @jalopezg @vvassilev I’ll contact you next week to see whether we can come up with a solution. Thanks for bringing this up, @weibin !

But until then, the workaround is to assign the temporary substr() result to a std::string.

Hi @weibin,

Thanks for bringing up this! Indeed, input.substr(0, idx) creates a std::string, copying characters from the original buffer. However, the constructed object is an r-value, i.e. the underlying buffer that you get via .c_str() is not valid after destruction. This memory might get overwritten at any time.

I don’t know if we can workaround this in the interpreter, though. Perhaps, we can discuss it, @Axel, @vvassilev.

Cheers,
J.

I think you were right? (EDIT: as Javi says, ) substr returns a new std::string, which goes out of scope right after the statement is executed, leaving a pointing to invalid memory.

I would not expect a different behavior from this, actually. cling prints the contents of a, and that’s correctly garbage :slight_smile:

@weibin when you run this code as a script it just might happen that the memory pointed by a is not overwritten with different contents (it could be, it just happens not to be) – the use-after-delete is there but by chance it does not have visible effects.

Thank you.

I misread, there’s indeed nothing for us to fix.

const char * a = func_returning_a_std_string();

is undefined behavior; this has nothing to do with cling. Sorry I didn’t see the variable assignment before.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.