C++ free()运算符是否从动态变量中删除地址? 让我们考虑下面的程序: int main () { int *p, *r; p = (int*)malloc(sizeof(int)); cout<<"Addr of p = "<<p <<endl; cout<<"Value of p = "<<*p <<endl; free(p); cout<<"After free(p)"<<endl; r = (int*)malloc(sizeof(int)); cout<<"Addr of r = "<<r <<endl; cout<<"Value of r = "<<*r <<endl; *p = 100; cout<<"Value of p = "<<*p <<endl; cout<<"Value of r = "<<*r <<endl; return 0; }
在上面的代码中,p和r是动态创建的。 p被创建并释放r是在释放p后创建的。 更改p中的值时,r的值也会更改。但是我已经释放了p的内存,那么为什么在更改p的值时,r的值也会被修改为与p相同的值呢 我得出以下结论。请评论我是否正确 说明: 指针变量p和q是动态声明的。垃圾值最初存储。指针变量p被释放/删除。声明另一个指针变量r。分配给r的地址与p的地址相同(p仍然指向旧地址)。现在,如果修改了p的值,r的值也会被修改为与p的值相同的值(因为两个变量都指向相同的地址)。C++ free()运算符是否从动态变量中删除地址? 让我们考虑下面的程序: int main () { int *p, *r; p = (int*)malloc(sizeof(int)); cout<<"Addr of p = "<<p <<endl; cout<<"Value of p = "<<*p <<endl; free(p); cout<<"After free(p)"<<endl; r = (int*)malloc(sizeof(int)); cout<<"Addr of r = "<<r <<endl; cout<<"Value of r = "<<*r <<endl; *p = 100; cout<<"Value of p = "<<*p <<endl; cout<<"Value of r = "<<*r <<endl; return 0; },c++,heap,dynamic-allocation,C++,Heap,Dynamic Allocation,在上面的代码中,p和r是动态创建的。 p被创建并释放r是在释放p后创建的。 更改p中的值时,r的值也会更改。但是我已经释放了p的内存,那么为什么在更改p的值时,r的值也会被修改为与p相同的值呢 我得出以下结论。请评论我是否正确 说明: 指针变量p和q是动态声明的。垃圾值最初存储。指针变量p被释放/删除。声明另一个指针变量r。分配给r的地址与p的地址相同(p仍然指向旧地址)。现在,如果修改了p的值,r的值也会被修改为与p的值相同的值(因为两个变量都指向相同的地址)。 运算符free()仅从指针变量
运算符free()仅从指针变量中释放内存地址,并将地址返回操作系统以供重用,但指针变量(p在本例中)仍然指向相同的旧地址。您对实际发生的情况的分析是正确的;但是,不能保证程序以这种方式可靠运行。每次在
free(p)
之后使用p
“都会引发未定义的行为”。(当您访问*p
和*r
时也会发生这种情况,而您没有先在其中写入任何内容。)未定义的行为比产生不可预测的结果更糟糕,也比可能导致程序崩溃更糟糕,因为编译器被明确允许假设引发未定义行为的代码永远不会执行。例如,编译器将您的程序视为与
int main() {}
因为您的程序中没有不引发未定义行为的控制流路径,所以程序一定永远不会运行 free()函数和delete
运算符不会更改指针的内容,因为指针是通过值传递的
但是,使用free()
或delete
后,指针指向的位置中的内容可能不可用
因此,如果我们有内存位置0x1000:
+-----------------+
0x1000 | |
| stuff in memory |
| |
+-----------------+
让我们假设指针变量p
包含0x1000,或指向内存位置0x1000
调用free(p)
后,允许操作系统在0x1000处重用内存。它可能不会立即使用它,也可能会将内存分配给另一个进程、任务或程序
但是,变量
p
没有改变,因此它仍然指向内存区域。在这种情况下,变量p
仍然有一个值,但您不应该取消引用(使用内存),因为您不再拥有内存。您的分析在某些方面表面上接近,但不正确
p
和r
被定义为main()
的第一条语句中的指针。系统不会动态创建。它们被定义为带有main()
的自动存储持续时间变量,因此当main()
创建和释放的不是p
malloc()
动态分配内存,如果分配成功,则返回一个指针,该指针标识动态分配的内存(如果动态分配失败,则返回一个NULL
指针),但不初始化该内存。malloc()
返回的值(在转换为指向int
的指针后,这在C++中是必需的)分配给p
然后,您的代码将打印p
的值
(我已经用斜体突出显示了下一段,因为我将在下面再次提到它)
下一条语句打印*p
的值。这样做意味着访问p
指向的地址处的值。但是,该内存未初始化,因此访问*p
的结果是未定义的行为。在您的实现(编译器和库)中,此时会产生一个“垃圾值”,然后将其打印出来。然而,这种行为并不能保证——它实际上可以做任何事情。不同的实现可能会产生不同的结果,例如异常终止(程序崩溃)、重新格式化硬盘驱动器,或者[在实践中不太可能]原语通过计算机的扬声器播放歌曲“崩溃”
调用free(p)
后,您的代码将按照与指针r
类似的顺序运行
赋值*p=100
具有未定义的行为,因为p
保存第一次malloc()
调用返回的值,但该值已传递给free()
。因此,就您的程序而言,内存不再保证存在
之后的第一个cout
语句访问*p
。由于p
不再存在(已被传递到free()
),这将导致未定义的行为
之后的第二个cout
语句访问*r
。该操作具有未定义的行为,原因与我在上面斜体段落中描述的完全相同(对于p
,当时是这样)
但是,请注意,代码中出现了五次未定义的行为。即使是一个未定义的实例
+-----------------+
0x1000 | |
| stuff in memory |
| |
+-----------------+
#include <iostream>
#include <cstdlib>
using namespace std;