IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

在函数外存取局部变量的一个比喻

酷壳 - CoolShell.cn 2011-08-19 23:14:53 累计浏览 3,471 次
本机暂存

    在StackOverflow上一这样一个关于C/C++的问题,问问题的人给了一个代码如下:

int * foo()
{
    int a = 5;
    return &a;
}

int main()
{
    int* p = foo();
    cout << *p;
    *p = 8;
    cout << *p;
}

    你可以编译并运行这个代码(编译时会有一个Warning),结果是:5 8。看上去你可以存取一个函数内的局部变量。但这和我们理解的不一样――函数内的变量在函数退出时就被释放了,不应该在外部还可以被引用。当然,对于C/C++熟悉的人都知道其实并不是真正的释放,你依然还可以通过内存地址去进行操作,这是C/C++的内存管理的不安全性――指针可以用来乱指。

    这个问题的解答是比较简单的,但是这个问题有一个答案中的比喻非常精彩。这个比喻是这样的――

    你在某个酒店订了一个房,你入住的时候,你放了一本书在这个酒店的抽屉里,但是你走的时候,你忘了这本书。而且,你还没有把这个房间的钥匙还回去。于是,你在未来某个时候,偷偷地回来,打开这个房间的门,你看到了你的书还在里间。当然,还还可以放回别的书。因为,这个酒店管理不会在你走的时候把你留下的书清走,而且,这个酒店的管理的安保措施不是那么严格,因为他信任每一个客人都会遵守管理条例。

    在这种情况下,如果你幸运的话,书还会在那里,也可能你的书已经没了。也有可能当你回去的时候,有一个人在那里正在撕你的书,或者酒店把那个抽屉都挪走并变成衣柜,或是整个酒店正在被拆除以改成了一个足球场,而你偷偷摸摸进到施工现场的时候被炸死。

    真是很精彩的比喻。这就是C/C++的不安全的地方,也正是Linus说的,C++是一门恐怖的语言是因为有很多不合格的程序员在使用它。就像你看到小孩子玩火一样的恐怖。

    关于这个事,还有一个比较经典的示例如下―― 函数a的初始化会影响函数b的数组。注意函数a中的 volatile 关键字。

#include 
using namespace std; 
void a()
{
    volatile int array[10];
    for (int i = 0; i < 10; i++)
        array[i] = i;
}

void b()
{
    int array[10];
    for (int i = 0; i < 10; i++)
        cout << array[i];
}

int main()
{
    a();
    b();
}

    真是可爱的C/C++。

同分类推荐文章

  1. 绿盟科技《APT组织研究年鉴》(2026 版)正式发布 (2026-06-16 20:21:10)
  2. 【已复现】Linux内核Fragnesia权限提升漏洞(CVE-2026-46300) (2026-06-15 10:53:58)
  3. 企业文档安全最佳实践(二):给文档上“身份证”——手动标密与智能自动标密 (2026-06-12 17:18:33)

查看更多 安全 文章 →

建议继续学习

  1. Linus:利用二级指针删除单向链表 (累计阅读 13,248)
  2. 内存越界的概念和调试方法 (累计阅读 7,275)
  3. GDB中应该知道的几个调试方法 (累计阅读 6,672)
  4. 自动化测试中Python与C/C++的混合使用 (累计阅读 5,299)
  5. GLIBC内存分配机制引发的“内存泄露” (累计阅读 5,240)
  6. 用vim在代码文件中自动添加#ifdef,#define,#endif的头文件宏定义 (累计阅读 4,783)
  7. 为什么重复free()比内存泄漏危害更大 (累计阅读 4,008)
  8. 64位平台C/C++开发注意事项 (累计阅读 3,147)
  9. 内存寻址原理 (累计阅读 2,989)
  10. Go 语言初学实践(2) (累计阅读 2,593)