当我尝试访问已经释放的地址时,程序将正常运行。有些货物要避免吗?比如名为have_alloca(void *p)
的某个函数可以返回p
是否为有效地址
我知道valgrind
与tool=memcheck
可以做到这一点。但我想知道我是否可以从代码中避免它
这是一个简单的例子:
#include <stdlib.h>
int main(int argc, char *argv[])
{
int *p = malloc(sizeof(int) * 10);
free(p);
*(p + 1) = 100;
return 0;
}
为什么我可以访问无效地址?程序可以编译运行,没有任何警告。 顺便说一句:Linux。
答案 0 :(得分:11)
不,你必须自己照顾好这个 从技术上讲,从语言标准的角度来看,写入不属于您的内存位置是未定义行为。
C和C ++语言为您提供了灵活地访问变量地址并使用它们,代价是您负责这些地址包含变量/对象拥有的有效值。
理由是:
“更大的力量带来了更大的责任”
所以你的责任就在于你。
答案 1 :(得分:8)
p就像一个普通变量
免费函数调用(p)只释放我们分配的内存,但p仍然保持地址值。除非你自己重置:
p = NULL;
所以请记住以下提示:
答案 2 :(得分:2)
NULL
指定给指针。NULL
。答案 3 :(得分:1)
除了其他回复之外,您可以考虑使用Boehm's conservative garbage collector,然后使用GC_malloc
代替malloc
,您将不会执行任何free
(甚至如果,当绝对确定内存区域变得无用且无法访问时,您可以明确地GC_free
它。
但 C 的要点是不允许您使用free
- d数据区。这样做是未定义的行为,任何事情都可能发生。
关于“为什么有时你仍然会访问一个无效的地址”(在free
- d区域内)的问题,答案是特定于实现的。实际上,在Linux上,从内核获取内存是通过mmap(2)(或有时是sbrk(2)
)完成的,然后通过munmap(2)
系统调用来完成释放,这是一些昂贵的操作和处理多个页面长度(通常为4Kbytes)。因此malloc
实现会尝试避免执行大量mmap
和munmap
系统调用,因此通常会以不同方式管理free
- d内存区域,方法是将它们组织起来以便它们可以在没有进行任何malloc
系统调用的情况下由另一个mmap
重用。这解释了内存区域仍然存在(即使它在malloc
内部簿记内),您可以访问它。但这样做会破坏malloc
的内部不变量,并且会在以后发生破坏。
BTW,如果地址在地址空间内,则地址有效,并且您可以通过读取(顺序)/proc/1234/maps
文件(在Linux上具有某些指定文本内容的伪文件)来查询进程1234的地址空间)。从流程内部读取/proc/self/maps
。尝试使用cat /proc/self/maps
命令,该命令显示运行该cat
命令的进程的地址空间以了解更多信息。请参阅proc(5)手册页。
尝试strace
您的简单程序,以了解它正在做什么系统调用。