Joh*_*nck 6 c++ gcc g++ undefined-behavior
此代码具有未定义的行为:
#include <string>
std::string make_str(const char* s)
{
return s;
}
const char* get_str(const std::string& s)
{
return s.c_str();
}
const char* bad()
{
return get_str(make_str("hello"));
}
Run Code Online (Sandbox Code Playgroud)
bad函数创建一个临时的std :: string并返回一个指向其数据的指针,该函数一返回就无效.
GCC 5+捕获这个("函数返回局部变量的地址")但仅在编译时-O3.在更典型的优化级别,包括-O2,GCC编译它没有抱怨,即使有-Wall -Wextra.除非你使用实验性-Wlifetime功能,否则Clang永远不会捕获它.
我的问题是:我们能否明确地告诉编译器这样的生存依赖性,例如使用属性?例如,我希望能够这样做:
[[lifetime-depends : s]] // hypothetical syntax
const char* get_str(const std::string& s);
Run Code Online (Sandbox Code Playgroud)
或许这个:
const char* get_str(const std::string& s)
__attribute__((lifetime-depends(0))); // hypothetical syntax
Run Code Online (Sandbox Code Playgroud)
我会接受一个适用于任何GCC或Clang官方版本的答案,但更喜欢GCC 6.1和C++ 14.Clang的实验-Wlifetime不是一个答案,因为我想要明确,而不是依赖于启发式方法(无论如何,它似乎不适用于多个翻译单元).
或者,我会接受一个答案,说明为什么这样做不会有用或不可行.
恕我直言,这意味着编译器智能捕获用户错误的可靠性非常高,因为这是您发布的代码,失败了。该标准已经涵盖了如何处理临时对象的生命周期,并且确实考虑在参考仍在使用的情况下延长生命周期(参见草案n4713,例如 15.2 项目符号 5)。但是,您发布的示例是不同的情况......
此外,虽然论文p1179r0 (PW 的评论)确实提供了指向存储在堆栈上的对象的指针的想法,但它对堆上的对象没有帮助。又应该如何呢?返回指向 char (或任何类型)的指针不是错误...返回指向不再存在的数组的指针是错误。它如何知道 c_str() 返回一个指向在其析构函数中删除的临时数组的指针(有点具体,不是吗?)?如何知道数组是否被破坏?通过查看析构函数是否完成了删除?如果析构函数不删除怎么办?警告析构函数应该删除?如果new是一个新的展示位置怎么办?如果……工厂模式……怎么办?如果为智能指针创建指针(例如:shared_ptr)怎么办...?如果另外 200 点...管理堆上的生命周期,主要会导致垃圾收集,该怎么办?
我认为您收到的警告function returns address of local variable [-Wreturn-local-addr]与您的代码无关,而更多的是由短字符串优化引起的“意外”。SSO 优化确实std::string 会返回一个指向本地的指针,如消息所示...简单测试,使字符串长度超过 16 个字符,警告就会消失...
| 归档时间: |
|
| 查看次数: |
245 次 |
| 最近记录: |