是否可以在 "new" 释放 "legally" 之后重复使用指针,直到再次返回相同的地址?
Is it possible to reuse pointer after free "legally" by "new" repeatedly until the same address returned again?
我知道如果对象被删除地址被释放,如果写入内容,它正在使用悬挂指针:
delete a;
memmove(a,new A(),sizeof(A));
所以,我尝试通过重复创建对象来重用指针 "legally"(没有未定义的行为),直到再次分配相同的地址:
#include <stdio.h>
int main(){
int* a=new int;
delete a;
int* b=new int;
while(b!=a){
delete b;
b=new int;
*b=123;
}
printf("%d\n",*a);
return 0;
};
在代码中b应该被分配直到获得相同的地址然后*a最终应该是123因为它指向b,但是我运行代码几次*a的值仍然是0 ,为什么会这样?这段代码是未定义的行为吗?或者只是因为不可能以这种方式重用指针?
我试过改删a;删除 b;在 while 循环中,但它仍然多次打印 0。
不,这是不合法的。你可以通过重复分配获得一个新的、合法的指针这一事实与释放后立即内存页仍由进程拥有这一事实一样无关紧要。
另外还有2个问题,我猜是错别字造成的:
- 多次取消分配 a.
- 内存泄漏:在循环中为 b 反复分配内存,但 b 从未被取消分配。
这条语句,
while(b!=a)
已经是未定义行为,因为 a
不是有效指针。然后UB多一点,UB多一点。
我认为你打印了 *a = 0
因为你双删除了 a
。但是如果你更正我认为你的程序确实有些道理
#include <stdio.h>
int main(){
int* a=new int;
delete a;
int* b=new int;
while(b!=a){
delete b;
b=new int;
*b=123;
}
printf("%d\n",*a);
return 0;
}
这是我的理解
- 你
new
和 delete
a
。删除后,a
将成为一个指向某个内存地址(比如 0xff00
)的悬空指针。由于您已经删除了该地址的对象 (int
),因此可以免费用于后续分配。
- 然后,您
new
和 delete
b
直到另一个对象 (int
) 在 0xff00
分配。现在,由于变量 a
仍然具有相同的地址,您可以跳出循环并在该地址打印任何内容。
这就是你想要做的吗?我在那里没有看到任何非法内容(使用已删除的指针没有任何问题,只是取消引用它是非法的,而你没有)
你确定赋值*b = 123
的代码真的执行了吗?很可能 b==a
在进入 while
循环之前,您只是不分配 *b
。像这样尝试:
#include <stdio.h>
int main(){
int* a=new int;
delete a;
int* b=new int;
while(b!=a){
delete b;
b=new int;
}
*b = 123;
printf("%d\n",*a);
return 0;
}
我不明白为什么代码是非法的,因为你可以从你想要的地方获取指针,就像你可以从 stdin
读取它们或者从网络获取或随机生成地址直到它们指向您可以使用它们的有效地址。
P.S。我阅读了 Cheers and hth. - Alf
答案及其下方的评论,并阅读了一些关于 "using invalid pointer value" 确切含义的解释,它是 UB。所以我在上面弄错了。好消息是使用来自有效地址的递增一次指针是合法的,所以写像 for (iter = begin; iter < end; ++iter) {...}
这样的循环不是 UB,即使 end
没有指向你可以使用的地址。
我知道如果对象被删除地址被释放,如果写入内容,它正在使用悬挂指针:
delete a;
memmove(a,new A(),sizeof(A));
所以,我尝试通过重复创建对象来重用指针 "legally"(没有未定义的行为),直到再次分配相同的地址:
#include <stdio.h>
int main(){
int* a=new int;
delete a;
int* b=new int;
while(b!=a){
delete b;
b=new int;
*b=123;
}
printf("%d\n",*a);
return 0;
};
在代码中b应该被分配直到获得相同的地址然后*a最终应该是123因为它指向b,但是我运行代码几次*a的值仍然是0 ,为什么会这样?这段代码是未定义的行为吗?或者只是因为不可能以这种方式重用指针?
我试过改删a;删除 b;在 while 循环中,但它仍然多次打印 0。
不,这是不合法的。你可以通过重复分配获得一个新的、合法的指针这一事实与释放后立即内存页仍由进程拥有这一事实一样无关紧要。
另外还有2个问题,我猜是错别字造成的:
- 多次取消分配 a.
- 内存泄漏:在循环中为 b 反复分配内存,但 b 从未被取消分配。
这条语句,
while(b!=a)
已经是未定义行为,因为 a
不是有效指针。然后UB多一点,UB多一点。
我认为你打印了 *a = 0
因为你双删除了 a
。但是如果你更正我认为你的程序确实有些道理
#include <stdio.h>
int main(){
int* a=new int;
delete a;
int* b=new int;
while(b!=a){
delete b;
b=new int;
*b=123;
}
printf("%d\n",*a);
return 0;
}
这是我的理解
- 你
new
和delete
a
。删除后,a
将成为一个指向某个内存地址(比如0xff00
)的悬空指针。由于您已经删除了该地址的对象 (int
),因此可以免费用于后续分配。 - 然后,您
new
和delete
b
直到另一个对象 (int
) 在0xff00
分配。现在,由于变量a
仍然具有相同的地址,您可以跳出循环并在该地址打印任何内容。
这就是你想要做的吗?我在那里没有看到任何非法内容(使用已删除的指针没有任何问题,只是取消引用它是非法的,而你没有)
你确定赋值*b = 123
的代码真的执行了吗?很可能 b==a
在进入 while
循环之前,您只是不分配 *b
。像这样尝试:
#include <stdio.h>
int main(){
int* a=new int;
delete a;
int* b=new int;
while(b!=a){
delete b;
b=new int;
}
*b = 123;
printf("%d\n",*a);
return 0;
}
我不明白为什么代码是非法的,因为你可以从你想要的地方获取指针,就像你可以从 stdin
读取它们或者从网络获取或随机生成地址直到它们指向您可以使用它们的有效地址。
P.S。我阅读了 Cheers and hth. - Alf
答案及其下方的评论,并阅读了一些关于 "using invalid pointer value" 确切含义的解释,它是 UB。所以我在上面弄错了。好消息是使用来自有效地址的递增一次指针是合法的,所以写像 for (iter = begin; iter < end; ++iter) {...}
这样的循环不是 UB,即使 end
没有指向你可以使用的地址。