范围结束后解除分配

时间:2012-10-20 08:37:01

标签: c++ memory-management segmentation-fault lifetime

  

可能重复:
  Returning the address of local or temporary variable
  Can a local variable’s memory be accessed outside its scope?

假设我们有以下代码

int *p;//global pointer
void foo() {
  int a=10;//created in stack
  p = &a;
}//after this a should be deallocated and p should be now a dangling pointer
int main() {
  foo();
  cout << *p << endl;
}

我想知道为什么会这样......应该是段故障!

确定未定义的行为似乎是合适的..可以再次验证它吗?我试图在下面的代码中模拟上面的内容,但现在它给出了SIGSEGV。

int main() {
    int *p=NULL;
    {
        int i=5;
        int *q = &i;
        p=q;
        delete q;//simulates the deallocation if not deallocated by the destructor..so p becomes a dangling pointer
    }
    cout << *p << endl;
}

3 个答案:

答案 0 :(得分:3)

您已编写了一个包含未定义行为的程序。 UB并不意味着段故障,它意味着任何事情都可能发生。你运行了你的程序,发生了一些事情,而不是你所期望的。故事的道德是不要用UB编写程序,如果你这样做,事情就很难理解。

答案 1 :(得分:1)

您不应该使用全局变量。在您的示例中,您所做的是未定义的行为

如果你做过像

这样的事情
int* foo() {
  int a = 10; //created in stack
  return &a;
}

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

你至少会收到警告:

prog.cpp:5: warning: address of local variable ‘a’ returned

你应该非常认真地对待这些警告。

答案 2 :(得分:-1)

当你在函数中定义一个变量时,它将被分配在堆栈上,当你从该函数的函数析构函数返回时,将自动调用该函数(如果type有任何析构函数),但与堆分配的对象不同,堆栈的内存将会在这一点上没有被释放:

void test1() {
    // assume on start of this function top of stack is 0x100
    int a = 10; // push 10 on to of stack and increase top of stack
                // Now top of stack is 0x100 + sizeof(int)
    a = 20;     // when you do this you are actually changing variable on stack
    p = &a;     // Get address of variable in stack!
                // So p is now 0x100
    // hidden return will restore top of stack to 0x100, pop return address, ...
}
int test2() {
    // again top of stack is 0x100
    int a2;     // a2 is in same address as a in previous function!
    a2 = 100;   // so this will overwrite value that pointed by p
                // because it point to same location
    return (int)&a2;
}

void main() {
    test1();
    test2();
    std::cout << *p << std::endl;
}

但是如果你的类型是一个具有析构函数并且在使用之前需要构造的类,那么你甚至可能会收到像分段错误这样的异常