const char *值生存期 [英] const char * value lifetime

查看:93
本文介绍了const char *值生存期的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

编辑:该问题中的代码为何起作用的问题已由重复标记中的链接问题回答。



我试图了解 const指向的字符串的方式和时间。 char * 被释放。



考虑:

  const char ** p = nullptr; 

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

cout<< * p;

离开内部范围后,我期望 p 成为指向 const char * 的悬挂指针。但是在我的测试中却不是。这意味着即使 t 超出范围, t 的值实际上仍然有效并可以访问。 / p>

这可能是由于将临时对象绑定到const引用而延长了其寿命。但是我却没有这样做,甚至通过将对 t 的引用保存在成员变量中并在以后从其他函数打印该值仍能得到正确的值。

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

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

私人:
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 * 的值?

解决方案

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



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



标准说:


计算字符串文字会导致字符串文字对象具有静态存储期限,并根据上述指定的字符进行初始化。


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



p 的值是 t 的地址。当 t 超出范围时,它变为无效指针,但这并不意味着存储在该地址的值突然变得不可访问或被擦除。表达式 * p 是未定义的行为,但是它似乎可以正常工作,因为还没有任何东西可以重用该内存位置,所以 * p 仍然包含字符串文字的地址。有关更多信息,请参见


是否可以访问局部变量的内存?

EDIT: The question about why the code in this question works has been answered by the linked question in the duplicate marking. The question about string literal lifetime is answered in the answer to this question.

I am trying to understand how and when the string pointed to by const char * gets deallocated.

Consider:

const char **p = nullptr;

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

cout << *p;

After leaving the inner scope I would expect p to be a dangling pointer to const char *. However in my tests it is not. That would imply that the value of t actually continues to be valid and accessible even after t gets out of scope.

It could be due to prolonging the lifetime of the temporary by binding it to const reference. But I do no such thing and even by saving the reference to t in a member variable and printing the value from different function later still gives me its correct value.

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

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

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

So what is the lifetime of the t's value here? I would say I am invoking undefined behaviour by dereferencing a pointer to a value of a variable that went out of scope. But it works every time so I think that is not the case.

When trying some other type like QString:

QString *p = nullptr;

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

cout << *p;

the code always prints the value correctly too even though it should not. str went out of scope with its value and I have not prolonged its lifetime by binding it to const reference either.

Interestingly the class example with QString behaves as I would expect and test2() prints gibberish because the value indeed went out of scope and m_P became dangling pointer.

So what is the actual lifetime of const char *'s value?

解决方案

The variables p and t are stack variables that you declared, so they have a lifetime that ends at the end of their enclosing block.

But the value of t is the address of the string literal "test", and that is not a variable you declared, it's not on the stack. It's a string literal, which is a constant defined in the program (similar to the integer literal 99 or the floating point literal 0.99). Literals don't go out of scope as you expect, because they are not created or destroyed, they just are.

The standard says:

Evaluating a string-literal results in a string literal object with static storage duration, initialized from the given characters as specified above.

So the object that the compiler creates to represent the literal "test" has static storage duration, which is the same duration as globals and static variables, meaning it doesn't go out of scope like a stack variable.

The value of p is the address of t, which does become an invalid pointer when t goes out of scope, but that doesn't mean that the value stored at that address suddenly becomes inaccessible or gets wiped. The expression *p is undefined behaviour, but it appears to work because nothing has reused that memory location yet so *p still contains the address of the string literal. For more details on that see the top answer to Can a local variable's memory be accessed outside its scope?

这篇关于const char *值生存期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆