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();
//直到这一点,才有明确的结果
//您甚至可以打印返回的地址
//但是是的,可能是一只虫子

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;
返回&tmp;
}
int main(){
int*a=ref();
//直到这一点,才有明确的结果
//您甚至可以打印返回的地址
//但是是的,可能是一只虫子

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


但我同意Mark B的观点,即结果行为是未定义的。

您是否在启用Optimizer的情况下编译了程序?
foo()
函数非常简单,可能已在结果代码中内联或替换


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

C++中,你可以访问任何地址,但是这并不意味着你应该访问。你访问的地址不再有效。它是因为FO返回后没有其他的内存被加扰,但是它可能在很多情况下崩溃。试试你的程序,或者EVE。在编译C++中,你可以访问任何地址,但是这并不意味着你应该访问。你访问的地址不再有效。它是因为FO返回后没有其他的内存被加扰,但是它可能在很多情况下崩溃。尝试分析你的程序,甚至只是编译它。ED,并且……< /P> < P>你从不通过访问无效内存抛出C++异常。你只是举一个引用任意内存位置的一般思想的例子。我可以这样做:

unsigned int q = 123456;

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

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


    在正常程序执行过程中,没有人会自动检查内存地址的语义有效性。然而,内存调试器,如<代码> Valgnnd>代码>将很高兴地执行此操作,因此您应该运行程序并通过它来查看错误。

    < P>您不会因为访问无效内存而抛出C++异常。ust给出了一个引用任意内存位置的总体思路示例。我可以这样做:

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

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


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

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


    但是,这是一种未定义的行为,您不应该依赖它来工作!

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

    然而,这是未定义的行为,您不应该依赖它来
    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;
    }