破坏局部变量是什么意思:
void f()
{
int x=10;
}
当该函数调用时,该局部变量的函数结束x将是什么?
对于:
void f2()
{
int a=100;
int* b=&a;
}
f2()那个局部变量的值到底是什么b?指针会b是一个悬空指针(有地址但没有任何值)吗?
当该函数调用时,该局部变量 x 的函数结束将是什么?
不存在的。蒸发。汽。走了。
x这是一个具有自动生命周期的变量。“自动”是指当x超出范围时,它将被销毁。(不完全删除,因为该术语暗示调用delete)
所有自动变量也是如此,无论它们是整数、字符串、浮点数,甚至是指针:
void f2()
{
int a=100;
int* b=&a;
}
这里a和b都是自动变量。它们都将在其作用域结束时被销毁 - f2(). 但是,将被破坏的只是变量本身。如果一个自动变量是一个指针(例如,一个原始指针),那么指针所指向的东西将不会被破坏。考虑:
void f3()
{
char* p = new char [256];
}
p这里仍然是一个指针到字符类型的自动变量。p指向的东西不是自动的——它是动态分配的(我们使用过new)。
如上所述,p将被销毁,但它指向的内存不会。这是内存泄漏。为了解决这个问题,您必须delete:
void f3()
{
char* p = new char [256];
delete [] p;
}
现在指向的内存p已经被正确销毁,并且指针本身(p)将在其范围结束时被销毁,因为它是自动的。
生命周期p和p指向的内容没有任何联系。仅仅因为你delete p并不意味着它p 本身现在也被摧毁了。 p仍然是一个自动变量。
一个例子:
void f3()
{
char* p = new char [256];
cout << (void*) p << "\n"
delete [] p;
// p still exists, it just points to to nothing useable
cout << (void*) p << "\n"
}
之后delete,我们将 的值打印p到屏幕上。如果你运行它,你会看到p删除它之前的值并没有改变。 p本身不受delete [] p;. 但是在f3()'s 的右大括号处},它将超出范围并被销毁。
f()退出时,x将不复存在。从技术上讲,当然,它所使用的内存仍然存在,但是编译器/系统可以随意使用该内存空间。它最终会将它重用于完全不同的东西。
如果您获取的地址x并将其从函数中传递出去,那么取消引用该指针是最糟糕的未定义行为。例子:
int* f() {
int a;
return &a;
}
int main() {
int* pointer = f();
//int b = *pointer; //Undefined behaviour, the compiler could choose to format your harddrive now!
}
变量x, a, 和b都是局部变量,因此在函数返回后它们不再存在。x如果您尝试询问其中任何一个的值是什么,调试器可能会说“在此上下文中找不到”。
更详细地说,这些变量的内存是从堆栈中分配的,并在函数返回时返回到堆栈中。调用f()本质上是将值 10 放在堆栈顶部的上方;如果您随后int在未初始化的堆栈上创建另一个,它可能会以值 10 开始(您不应该依赖这种行为,因为它不能保证,但它让您了解堆栈如何在许多系统上工作)。
b不会是悬空指针,因为您没有在堆上分配任何内存(使用mallocor new,它只是指向局部变量地址的指针a(退出函数范围时被销毁)指针本身也会超出范围。指针f2在函数结束时被销毁,在这种情况下不会造成内存泄漏,因为它指向的对象在堆栈上并且不是用new.
但是,如果您考虑以下情况:
int *global;
void foo()
{
int a = 10;
global = &a;
}
然后指针在运行完成global后存在foo,但指向一个被销毁的超出范围的变量,其值未定义。
一旦该函数的堆栈帧被弹出......你不能引用那些局部变量
你没有破坏任何东西,你的变量超出了范围。
由于它没有分配堆,因此您不会在内存管理方面遇到任何问题。
如果你真的想学习这种机制的机制,你可以随时下载ollydbg(假设是windows),并在这个函数执行之前、期间和之后进入,以了解现代编程语言和编译器如何处理局部变量.