【问题标题】:const char * value lifetime [duplicate]const char *值生命周期[重复]
【发布时间】:2015-12-28 14:46:19
【问题描述】:

编辑:重复标记中的链接问题已回答了有关此问题中的代码为何起作用的问题。关于字符串字面量寿命的问题在这个问题的答案中得到了解答。

我试图了解const char * 指向的字符串如何以及何时被释放。

考虑:

const char **p = nullptr;

{
    const char *t = "test";
    p = &t;
}

cout << *p;

离开内部作用域后,我希望p 成为指向const char * 的悬空指针。但是在我的测试中它不是。这意味着即使在 t 超出范围之后,t 的值实际上仍然有效且可访问。

这可能是由于通过将其绑定到 const 引用来延长临时的生命周期。但是我没有这样做,即使将t 的引用保存在成员变量中并稍后从不同的函数中打印该值,仍然可以为我提供正确的值。

class CStringTest
{
public:
    void test1()
    { 
        const char *t = "test";
        m_P = &t;
        test2();
    }

    void test2() 
    { 
        cout << *m_P;
    }

private:
    const char **m_P = nullptr;
};

那么这里t 的值的生命周期是多少?我会说我通过取消引用指向超出范围的变量值的指针来调用未定义的行为。但它每次都有效,所以我认为情况并非如此。

尝试其他类型时,例如 QString:

QString *p = nullptr;

{
    QString str = "test";
    p = &str;
}

cout << *p;

代码总是正确地打印值,即使它不应该。 str 的值超出了范围,我也没有通过将其绑定到 const 引用来延长它的生命周期。

有趣的是,QString 的类示例的行为与我预期的一样,test2() 打印出乱码,因为该值确实超出了范围,m_P 变成了悬空指针。

那么const char *的值的实际生命周期是多少?

【问题讨论】:

  • 您无法测试是否有东西悬空。任何这样做的尝试都会产生未定义的行为。
  • 这基本上是stackoverflow.com/questions/6441218/… 的一个副本,另外还有一个关于字符串文字的生命周期的问题
  • “在我的测试中它不是” 大声笑你什么?

标签: c++ c++11


【解决方案1】:

变量pt 是您声明的堆栈变量,因此它们的生命周期在其封闭块的末尾结束。

但是t 的值是字符串文字"test" 的地址,这不是你声明的变量,它不在堆栈上。它是一个字符串字面量,是程序中定义的常量(类似于整数字面量99 或浮点字面量0.99)。字面量不会超出您的预期,因为它们没有被创建或销毁,它们只是

标准说:

评估一个字符串文字会产生一个具有静态存储持续时间的字符串文字对象,从上面指定的给定字符初始化。

因此编译器创建的用于表示文字"test" 的对象具有静态存储持续时间,与全局变量和static 变量的持续时间相同,这意味着它不会像堆栈变量那样超出范围。

p 的值是t 的地址,当t 超出范围时,它确实成为无效指针,但这并不意味着存储在该地址突然变得无法访问或被擦除。表达式 *p 是未定义的行为,但它似乎有效,因为尚未重用该内存位置,因此 *p 仍然包含字符串文字的地址。有关这方面的更多详细信息,请参阅Can a local variable's memory be accessed outside its scope? 的最佳答案

【讨论】:

    【解决方案2】:

    编译器将文字字符串放入一个静态分配的空间,该空间被加载到虚拟内存的受保护段中,这样这些字符串可以在进程的整个生命周期内共享(该值是一个常量,因此不需要不断涌现它们的开销)。寻找这样的东西被释放是浪费时间,因为它从未真正发生过。

    变量是堆栈分配的。字符串常量应该被认为是:一个字符串常量……就像数字 3。

    【讨论】:

      【解决方案3】:

      字符串字面量在静态存储中分配。

      如果你在程序的任何地方提到了字符串文字,就好像你提到了:

      static const char someUniqueIdentifier[]="the data";
      

      在全局范围内。

      const char* str = "some string"; 表示确保"some string" 在程序的静态部分中作为一个以空结尾的常量数组存在,并将str 指向它。

      但是,您在第一个示例中引用了自动(= 在堆栈上)指针,而不是静态存储字符串。这确实有一个生命周期限制在它的范围内,但是当你调用test2() 时,test1() 的范围还没有结束。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-01-08
        • 1970-01-01
        • 2019-03-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多