C++ 函数属性指示返回值的生命周期与参数相同

标签 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"));
}

错误的函数创建了一个临时的 std::string 并返回一个指向其数据的指针,该函数一返回就无效。

GCC 5+ 捕获此(“函数返回局部变量的地址”)但仅当使用 -O3 编译时。在包括 -O2 在内的更典型的优化级别,GCC 可以毫无怨言地编译它,即使使用 -Wall -Wextra。除非您使用实验性 -Wlifetime 功能,否则 Clang 永远不会捕获它。

我的问题是:我们能否明确地告诉编译器这种生命周期依赖性,例如使用属性?例如,我希望能够这样做:

[[lifetime-depends : s]] // hypothetical syntax
const char* get_str(const std::string& s);

或者可能是这样:

const char* get_str(const std::string& s)
  __attribute__((lifetime-depends(0))); // hypothetical syntax

我会接受适用于任何官方版本的 GCC 或 Clang 的答案,但更喜欢带有 C++14 的 GCC 6.1。 Clang 的实验性 -Wlifetime 不是答案,因为我想要明确,而不是依赖启发式方法(这似乎无论如何都不适用于多个翻译单元)。

或者,我会接受一个答案,说明为什么这没有用或无法实现。

最佳答案

基于意见的答案,不提供答案,但质疑问题背后的想法(并且评论的文字太多):

恕我直言,这意味着编译器智能在捕获用户错误方面具有相当大的可靠性,因为那是您发布的代码,失败了。该标准已经涵盖了如何处理临时对象的生命周期,并考虑在引用仍在使用的情况下延长生命周期(参见草案 n4713,例如 15.2 Bullet 5)。但是,您发布的示例是不同的情况...

同时,论文 p1179r0 (P.W 的评论)确实提供了指向存储在栈上 对象的指针的想法,它对堆上的对象没有帮助。又该如何呢?返回指向 char(或任何类型)的指针不是错误...返回指向不再存在的数组的指针是。它怎么知道 c_str() 返回一个指向一个临时数组的指针,这个数组在它的析构函数中删除了(有点具体,不是吗?)?如何知道数组是否被销毁?如果删除完成,通过查看析构函数?如果析构函数不删除怎么办?关于析构函数应该删除的警告?如果 new 是新展示位置怎么办?如果……工厂模式……怎么办?如果为智能指针(例如:shared_ptr)创建指针怎么办...?如果再增加 200 分会怎样……在堆上管理生命周期,主要会导致垃圾收集。

你得到的警告是 function returns address of local variable [-Wreturn-local-addr] 我认为这与你的代码无关,但更多的是“意外”造成的通过短字符串优化。 SSO 优化的 std::string does 如消息所述返回指向本地的指针...简单测试,使您的字符串长于 16 个字符,警告 disappears ...

关于C++ 函数属性指示返回值的生命周期与参数相同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54570121/

相关文章:

c++ - 为什么用户定义的字符串文字和整数文字有不同的行为?

c++ - 难忘的工厂 : When is constructor instantiated?

c++ - 模板特化适用于 gcc,但不适用于 visual studio 10

c++ - 使用 g++、make、cmakelists 在 linux openSUSE 上编译 googletest 程序

C++ 模板化友元类

C++类构造函数二维数组内存分配

c++ - 共享指针 (shared_ptr) 的 Boost Fusion 容器导致段错误 (sigsegv) 或垃圾结果

c - 使 C 浮点文字 float (而不是 double )

c++ - 指针分配和段错误

c++ - 无法编译 Crow 示例 - boost/optional.hpp : No such file or directory