获取临时std::string内部数组地址的未定义行为相关问题
你的初始分析完全正确
根据C++标准,std::string("test")属于临时对象,它的生命周期仅持续到它所在的完整表达式结束,也就是你赋值语句末尾的分号位置。临时对象析构时会释放内部存储字符串的内存,c_str()返回的指针指向的就是这块被释放的内存,因此ptr会变成悬空指针,访问该指针的行为属于未定义行为。
不同编译器的表现差异是未定义行为的典型特征
未定义行为的核心就是C++标准没有对运行结果做任何约束,编译器厂商可以自由选择实现逻辑,你遇到的两种情况都是合理的未定义行为表现:
- Visual Studio 2019的STL实现为了方便开发者调试,在
std::string析构时会主动擦除内部字符数组的内容,或者直接将对应内存块标记为无效调试页,所以你访问时会得到空字符串的结果,属于调试友好的实现逻辑。 - Android NDK使用的Clang对应的STL实现没有额外的调试擦除逻辑,内存释放操作只会把对应的内存块标记为空闲可分配,不会主动修改内存里的原有内容。在这块空闲内存还没有被其他分配操作占用改写之前,读取就会看到之前遗留的"test"字符串,这只是临时的巧合,没有任何可靠性,后续只要有其他内存分配操作占用了这块空间,内容就会被随机篡改。
这种悬空指针的写法在任何场景下都不可用,绝对不能依赖不同编译器的未定义行为表现写代码。
内容的提问来源于stack exchange,提问作者Yakov Dan
相关产品推荐
相关产品推荐

