销毁局部变量的含义是什么:
void f()
{
int x=10;
}
当该函数调用时,局部变量x的函数结束将是什么?
并且:
void f2()
{
int a=100;
int* b=&a;
}
结束f2()那个局部变量int * b'的值是多少? b指针将是悬空指针(将有地址,但没有任何值)?
答案 0 :(得分:9)
当该函数调用时,局部变量x的函数结束 是什么?
不存在。 Evaportated。汽。消失了。
x
这是一个具有自动生命周期的变量。 “自动”是指当x
超出范围时,它将被销毁。 (不完全已删除,因为该术语意味着调用delete
)
所有自动变量都是如此,它们是积分,字符串,浮点数,甚至是指针:
void f2()
{
int a=100;
int* b=&a;
}
此处a
和b
都是自动变量。它们都将在其范围的末尾被销毁 - f2()
的结尾。然而,所有将被破坏的都是变量本身。如果自动变量是指针(例如,原始指针),则指针指向的事物将不被销毁。考虑:
void f3()
{
char* p = new char [256];
}
p
这里仍然是一个自动变量,类型指针指向char。 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()
的右括号}
,它将超出范围并且会被破坏。
答案 1 :(得分:0)
变量x
,a
和b
都是局部变量,因此在函数返回后它们不再存在。如果你试图询问它们的价值是什么,调试器可能会说“在这种情况下找不到x
”。
更详细地说,这些变量的内存是从堆栈中分配的,并在函数返回时返回到堆栈。调用f()
基本上将值10放在堆栈顶部的上方;如果你然后在堆栈上创建另一个未初始化的int
,它可能会以值10开始(你不应该依赖这种行为,因为它不能保证,但它可以让你基本了解如何堆栈适用于许多系统)。
答案 2 :(得分:0)
b
不会是一个悬空指针,因为你没有在堆上分配任何内存(使用malloc
或new
,它只是一个指向本地地址的指针变量a
(在退出函数范围时销毁)答案 3 :(得分:0)
指针本身也将超出范围。指针f2
在函数结束时被销毁,这在这种情况下不会产生内存泄漏,因为它指向的对象在堆栈上而不是用new
创建的。
但是如果你考虑以下情况:
int *global;
void foo()
{
int a = 10;
global = &a;
}
然后指针global
在foo
完成运行后存在,但指向一个被破坏的超出范围的变量,其值未定义。
答案 4 :(得分:0)
弹出该函数的堆栈框架后...您无法引用这些局部变量
答案 5 :(得分:0)
当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!
}
答案 6 :(得分:0)
你没有摧毁任何东西,你的变量超出了范围。
由于没有分配堆,因此在内存管理方面不会有任何问题。
如果你真的想学习这种机制的机制,你可以随时下载ollydbg(假设是windows),并在执行此函数之前,期间和之后进入,以便了解现代编程语言和编译器处理局部变量。