Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
168 views
in Technique[技术] by (71.8m points)

c++ - What is the life cycle of a class instance returned by function?

Here's a program:

#include <cstring>
#include <iostream>
#include <string>
std::string fun(){
    return "this is a string";
}
int main(){
    const char *str = fun().c_str();
    if(strcmp(str, "this is a string1") == 0){
        std::cout << "ok" << std::endl;
    }
}

When I compiled with AddressSanitizer, I got:

=================================================================
==1841==ERROR: AddressSanitizer: heap-use-after-free on address 0x603000000010 at pc 0x7ffff7658c18 bp 0x7fffffffd800 sp 0x7fffffffcfa8
READ of size 1 at 0x603000000010 thread T0
    #0 0x7ffff7658c17  (/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/libasan.so.6+0x8cc17)
    #1 0x555555556500 in main /home/pqy/src/json/include/t.cpp:9
    #2 0x7ffff7073ed9 in __libc_start_main ../csu/libc-start.c:314
    #3 0x5555555561c9 in _start (/home/pqy/src/json/include/tt+0x21c9)

0x603000000010 is located 0 bytes inside of 17-byte region [0x603000000010,0x603000000021)
freed by thread T0 here:
    #0 0x7ffff767ce37 in operator delete(void*) (/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/libasan.so.6+0xb0e37)
    #1 0x5555555564d6 in main /home/pqy/src/json/include/t.cpp:8
    #2 0x7ffff7073ed9 in __libc_start_main ../csu/libc-start.c:314

previously allocated by thread T0 here:
    #0 0x7ffff767c317 in operator new(unsigned long) (/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/libasan.so.6+0xb0317)
    #1 0x7ffff74cfb6c in void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<char const*>(char const*, char const*, std::forward_iterator_tag) (/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/libstdc++.so.6+0x16fb6c)

SUMMARY: AddressSanitizer: heap-use-after-free (/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/libasan.so.6+0x8cc17)

Why the std::string returned by fun() is destroyed so quickly since main function hasn't finished yet?

question from:https://stackoverflow.com/questions/65949122/what-is-the-life-cycle-of-a-class-instance-returned-by-function

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

In this statement:

const char *str = fun().c_str();
// oops, str is invalid, since the temporary has been destroyed

fun returns a temporary std::string, and you're taking a pointer to that with c_str. However, that temporary dies at the end of the full expression, in this case at the ;. So you're left with a pointer that points to memory that no longer exists, which is what the sanitizer is telling you about.


You can fix this by assigning the returned std::string to an l-value, and this will ensure that the pointer you take with c_str will live till the end of main.

auto temp = fun();
const char *str = temp.c_str();
// ok, str is valid, since temp has not been destroyed

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...