函数返回的类实例的生命周期是什么?
这是一个程序:
#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;
}
}
当我用 AddressSanitizer 编译时,我得到:
=================================================================
==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)
函数还没有完成,为什么std::string返回的 byfun()这么快就被销毁main了?
回答
在此声明中:
const char *str = fun().c_str();
// oops, str is invalid, since the temporary has been destroyed
fun返回一个临时的std::string,并且您正在使用c_str. 但是,该临时在完整表达式的结尾处终止,在本例中为;. 所以你留下了一个指向不再存在的内存的指针,这就是消毒剂告诉你的。
您可以通过将返回std::string的值分配给左值来解决此问题,这将确保您使用的指针c_str将持续到main.
auto temp = fun();
const char *str = temp.c_str();
// ok, str is valid, since temp has not been destroyed