C++ 可以是局部变量';可以在其范围外访问的内存?

C++ 可以是局部变量';可以在其范围外访问的内存?,c++,memory-management,local-variables,dangling-pointer,C++,Memory Management,Local Variables,Dangling Pointer,我有以下代码 #include <iostream> int * foo() { int a = 5; return &a; } int main() { int* p = foo(); std::cout << *p; *p = 8; std::cout << *p; } #包括 int*foo() { INTA=5; 回报&a; } int main() { int*p=foo(); std::

我有以下代码

#include <iostream>

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

int main()
{
    int* p = foo();
    std::cout << *p;
    *p = 8;
    std::cout << *p;
}
#包括
int*foo()
{
INTA=5;
回报&a;
}
int main()
{
int*p=foo();

std::cout因为存储空间还没有被踩踏。不要指望这种行为。

您只是返回一个内存地址,这是允许的,但可能是一个错误

int * ref () {

 int tmp = 100;
 return &tmp;
}

int main () {

 int * a = ref();
 //Up until this point there is defined results
 //You can even print the address returned
 // but yes probably a bug

 cout << *a << endl;//Undefined results
}
是的,如果您尝试取消引用该内存地址,您将有未定义的行为

int * ref () {

 int tmp = 100;
 return &tmp;
}

int main () {

 int * a = ref();
 //Up until this point there is defined results
 //You can even print the address returned
 // but yes probably a bug

 cout << *a << endl;//Undefined results
}
int*ref(){
int tmp=100;
返回&tmp;
}
int main(){
int*a=ref();
//直到这一点,才有明确的结果
//您甚至可以打印返回的地址
//但是是的,可能是一只虫子

难道你编译程序时启用了Optimizer吗?
foo()
函数非常简单,可能在生成的代码中被内联或替换了


<>但是我同意Mark B的结果,行为是不确定的。

C++中,你可以访问任何地址,但是这并不意味着你应该访问。你访问的地址不再有效。它是因为FO返回后没有其他的内存被加扰,但是它可能在很多情况下崩溃。试试你的程序,或者EVE。n编译它优化,看到…

你从不通过访问无效内存抛出C++异常。你只是举一个引用任意内存位置的一般思想的例子。我可以这样做:

unsigned int q = 123456;

*(double*)(q) = 1.2;
在这里,我只是把123456当作一个double的地址,然后写信给它。可能会发生很多事情:

  • q
    实际上可能是double的有效地址,例如
    double p;q=&p;
  • q
    可能指向分配内存中的某个地方,而我只是覆盖了其中的8个字节
  • q
    指向分配的内存之外,操作系统的内存管理器向我的程序发送分段故障信号,导致运行时终止它
  • 你中了彩票
  • 按照设置的方式,返回的地址指向内存的有效区域更为合理,因为它可能只在堆栈的下面一点,但它仍然是一个无效的位置,您无法以确定的方式访问它


    在正常的程序执行过程中,没有人会自动为您检查内存地址的语义有效性。但是,诸如
    valgrind
    之类的内存调试器会很乐意这样做,因此您应该运行程序并查看错误。

    在典型的编译器实现中,您可以将代码视为“打印出地址为a的内存块的值”。此外,如果向包含本地
    int
    的函数添加新函数调用,则
    a
    的值(或
    a
    用于指向的内存地址)很有可能这是因为堆栈将被包含不同数据的新帧覆盖

    然而,这是未定义的行为,您不应该依赖它来工作

    怎么可能呢?局部变量的内存不是在其函数之外无法访问吗

    你租了一间酒店房间。你把一本书放在床头柜最上面的抽屉里睡觉。你第二天早上退房,但“忘了”还你的钥匙。你偷了钥匙

    一周后,你回到酒店,不办理入住手续,带着偷来的钥匙溜进你的旧房间,看看抽屉里的东西。你的书还在那里。令人惊讶

    这怎么可能?如果你没有租过房间,难道酒店房间抽屉里的东西就无法进入吗?

    很明显,这种情况在现实世界中是可以发生的。当你不再被授权进入房间时,不会有神秘的力量使你的书消失。也不会有神秘的力量阻止你带着偷来的钥匙进入房间

    酒店管理层不需要拿走你的书。你没有和他们签订合同说如果你留下东西,他们会为你把它撕碎。如果你非法带着偷来的钥匙重新进入房间取回,酒店保安人员不需要抓到你偷偷溜进来。你没有和他们签订合同说“如果我晚些时候想偷偷溜回我的房间,你必须阻止我。”相反,你和他们签订了一份合同,上面写着“我保证晚些时候不会再偷偷溜回我的房间”,这是你违反的合同

    在这种情况下,任何事情都有可能发生。这本书可能在那里——你很幸运。其他人的书可能在那里,你的书可能在酒店的火炉里。当你进来的时候,有人可能就在那里,把你的书撕成碎片。酒店本可以把桌子和书全部移走,换成一个衣柜re酒店可能即将被拆毁,取而代之的是一个足球场,当你们在这里鬼鬼祟祟的时候,你们会死于一场爆炸

    你不知道会发生什么;当你离开酒店并偷了一把钥匙以便以后非法使用时,你放弃了在一个可预测的、安全的世界中生活的权利,因为你选择打破系统的规则

    <> > > C++不是一个安全的语言<强>,它会让你打破系统的规则。如果你试图做一些非法的、愚蠢的事情,比如回到房间,你就没有被授权进入并翻找一个甚至不在那里的桌子,C++就不会阻止你。比C++更安全的语言解决这个问题。通过限制您的权限来解决问题——例如,通过对键进行更严格的控制

    更新 天哪,这个答案得到了很多关注。(我不知道为什么——我认为这只是一个“有趣”的小比喻,但不管怎样。)

    我想用一些技术上的想法来更新这一点可能是密切相关的

    编译器在t中
    int *a()
    {
       int x = 5;
       return &x;
    }
    
    void b( int *c )
    {
       int y = 29;
       *c = 123;
       cout << "y=" << y << endl;
    }
    
    int main()
    {
       b( a() );
       return 0;
    }
    
    #include<stdio.h>
    #include <stdlib.h>
    int * foo(){
        int a = 5;
        return &a;
    }
    void boo(){
        int a = 7;
    
    }
    int main(){
        int * p = foo();
        boo();
        printf("%d\n",*p);
    }
    
    int * foo()
    {
       int *x = new int;
       *x = 5;
       return x;
    }
    
    int main()
    {
        int* p = foo();
        std::cout << *p << "\n"; //better to put a new-line in the output, IMO
        *p = 8;
        std::cout << *p;
        delete p;
        return 0;
    }