2015-09-30 85 views
1

编辑:有关此问题代码工作原因的问题已通过重复标记中的链接问题得到解答。关于字符串文字生存期的问题在这个问题的答案中得到了回答。const char * value lifetime

我想了解如何以及何时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以其价值超出了范围,并且我也没有通过将其与常量参考绑定来延长其寿命。

有趣的是,带有QString的类示例的行为与我所预期的相同,test2()会打印乱码,因为该值确实超出了范围,m_P成为悬挂指针。

那么const char *的实际使用寿命值是多少?

+4

您无法测试是否有什么悬挂。任何尝试这样做都会有不确定的行为。 –

+3

这基本上是一个重复http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope与一个问题关于字符串文字的生命期 –

+0

_“在我的测试中,它不是”_LOL你什么? –

回答

4

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

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

标准表示:

评价在具有静态存储持续时间的字符串文字对象,如上述规定的从给定的字符初始化的字串文本结果。

使编译器创建代表字面"test"具有静态存储时间,这是相同的持续时间和全局变量static,这意味着它不会超出范围像堆栈变量的对象。

p的值是t地址,这确实当t超出范围成为无效的指针,但这并不意味着存储在该地址的值突然变得不可访问或已被清除。表达式*p是未定义的行为,但它似乎工作,因为没有重用内存位置,所以*p仍包含字符串文字的地址。有关更多细节,参见顶部答案Can a local variable's memory be accessed outside its scope?

3

编译器把文字串到被加载到虚拟存储器的受保护节段静态分配空间,使得这些字符串可以在该方法的整个寿命共享(这个值是一个常数,所以不需要花费不断的开销来让它们存在)。寻找类似被释放的东西是浪费时间,因为它从来没有真正发生过。

变量是堆栈分配的。字符串常量应该被认为是:字符串常量...类似于数字3.

0

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

如果你提到一个字符串在程序中任何地方的文字,这是因为如果你做的事:

static const char someUniqueIdentifier[]="the data"; 
在全球范围内

const char* str = "some string";表示确保"some string"存在于程序的静态部分中的常量空终止数组,并指向str

然而,你在第一个例子中引用了你的自动(=在堆栈上)指针,而不是静态存储字符串。这确实有一个局限于它的范围,但是当你调用test2()时,test1()的范围尚未结束。