表示返回值生存期的C ++函数属性与参数

时间:2019-02-07 09:29:39

标签: 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在内的更典型的优化级别上,即使使用-Wall -Wextra,GCC也会毫无抱怨地对其进行编译。除非您使用实验性的-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并不是答案,因为我想明确一点,而不是依靠启发法(看来启发法无论如何都无法在多个翻译单元中工作)。

或者,我将接受一个答案,其中提供了为什么这样做无效或不可行的原因。

1 个答案:

答案 0 :(得分:4)

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

恕我直言,这将意味着在编译器智能方面非常可靠,可以捕获用户错误,因为那是您发布的代码,是失败的。该标准已经涵盖了如何处理临时人员的寿命,并且确实考虑在参考仍在使用的情况下延长寿命(请参见n4713草案,例如15.2项目符号5)。但是,您发布的示例是另一种情况...

此外,尽管论文p1179r0(P.W评论)确实提出了指向存储在堆栈上的对象的指针的想法,但它对堆上的对象没有帮助。怎么办?返回指向char(或任何类型)的指针不是错误...返回指向不再存在的数组的指针是。怎么知道c_str()返回一个指向在其中的析构函数中删除的临时wich数组的指针(特定于Kinda,不是吗?)?如何知道阵列是否被破坏?通过查看析构函数是否完成删除?如果析构函数不删除怎么办?警告析构函数应删除?如果new是新的展示位置怎么办?如果...工厂模式怎么办?如果为智能指针创建指针(例如:shared_ptr)呢?如果再增加200点呢?在堆上管理生存期,通常会导致垃圾回收。

您收到的警告是function returns address of local variable [-Wreturn-local-addr],我认为这与您的代码无关,但更多是由短字符串优化引起的“意外”。经过SSO优化的std::string 确实将消息返回指向本地的指针...简单测试,使您的字符串长度超过16个字符,警告disappears ... < / p>