通过从本地 C 样式数组返回指针来获取悬空指针

Posted

技术标签:

【中文标题】通过从本地 C 样式数组返回指针来获取悬空指针【英文标题】:Getting a dangling pointer by returning a pointer from a local C-style array 【发布时间】:2018-09-13 01:27:31 【问题描述】:

我对下面的代码有点困惑:

#include <iostream>

const char* f()

    const char* arr[]="test";
    return arr[0];


int main()

    auto x = f();
    std::cout << x;

在我看来,这段代码应该是 UB(未定义的行为)。我们返回一个指向本地范围内的 C 样式数组元素的指针。事情应该出错了。但是,我测试过的编译器都没有抱怨(我在 g++ 和 clang 上都使用了-Wall -Wextra -pedantic)。 valgrind 也不抱怨。

上面的代码是有效的还是像人们想象的那样是 UB?

PS:运行它似乎会产生“正确”的结果,即显示“测试”,但这并不表示正确性。

【问题讨论】:

FWIW 它在实践中“工作”的原因是常量字符串“test”被存储在可执行文件的静态数据区域中,因此即使在函数返回后字符串仍然有效。 (当然,语言规范是否保证它可以工作是另一个问题) 问这些问题没有坏处,而且这个问题写得很好。 +1。 @JesperJuhl 我知道 UB 是什么,以及月球可能因此而爆炸的事实。我在问代码是否真的是UB。看起来不是。看起来很多人认为代码是 UB……所以我认为这个问题很有用。 @Bathsheba 看来我们还在学习 :) 确实代码 不是 UB @vsoftco:没想到是这样,但需要像 Barry 这样的专家来指出原因。 【参考方案1】:

不,这不是 UB。

这个:

const char* f()

    const char* arr[]="test";
    return arr[0];

可以改写成等价的:

const char* f()

    const char* arr0 = "test";
    return arr0;

所以我们只是返回一个本地指针,指向一个字符串文字。字符串文字有static storage duration,没有任何悬垂。功能真的是一样的:

const char* f()

    return "test";


如果你做了类似这个的事情:

const char* f() 
    const char arr[] = "test"; // local array of char, not array of char const*
    return arr;

现在 是 UB - 我们正在返回一个悬空指针。

【讨论】:

"字符串字面量具有静态存储持续时间" - 我知道所有的编译器都这样做;但在标准中,字符串文字必须具有静态持续时间吗? @UKMonkey 是的,添加了参考。 不要迂腐,但这并不是真正的“等效”。从功能上讲,在这种情况下,当然,但数组就是数组。 ;) @LightnessRacesinOrbit,在这两种情况下,都有一个指向 const char 的本地指针,在这两种情况下,本地指针都被初始化为指向一个文字字符串,并且在这两种情况下都返回了它的值。唯一的区别是,在原始示例中,本地指针是单元素数组的成员,而在替代版本中,它是标量。那么,如果在某种意义上它们不是“等价的”呢?这里重要的不是局部变量的确切类型。重要的是字符串文字在函数返回后是否仍然有效。 C 还保证字符串文字具有静态存储持续时间,请参阅port70.net/~nsz/c/c11/n1570.html#6.4.5p6。【参考方案2】:

数组arr 具有本地存储持续时间,并将在范围结束时消失。然而,字符串文字"test" 是指向静态存储位置的指针。在返回之前将此指针临时存储在本地数组arr 中不会改变这一点。它始终是一个静态存储位置。

请注意,如果函数要返回 C++ 样式字符串类型而不是 C 样式 const char *,则根据 C++ 临时规则,额外的转换/簿记可能会使您的值在生命周期内受到限制。

【讨论】:

以上是关于通过从本地 C 样式数组返回指针来获取悬空指针的主要内容,如果未能解决你的问题,请参考以下文章

C vs 变量范围中的悬空指针问题

go语言之指针

C语言中的“悬空指针”和“野指针”是什么意思?

C语言指针初学者 请帮我看看下面的提 为啥调用函数返回值是char型的 这样不就只能返回一个字符了吗

c编程中的悬空指针[重复]

❤️野指针?悬空指针?❤️ 一文带你搞懂!