已经释放了记忆

时间:2011-07-30 01:49:27

标签: c free

在C中是否有任何方法可以知道以前是否已使用free()释放了内存块?我能做点像......

if(isFree(pointer))
{ 
    //code here
}

5 个答案:

答案 0 :(得分:8)

好的,如果您需要检查指针是否已被释放,您可能需要检查您的设计。您永远不必跟踪指针上的引用计数或是否已释放它。另外一些指针不是动态分配的内存所以我希望你的意思是用malloc()调用的。这是我的观点,但如果你有一个坚实的设计,你应该知道你的指针指向的东西何时被使用。

我看到的唯一不起作用的地方是单片内核,因为内存中的页面需要使用次数,因为共享映射等等。

在您的情况下,只需将未使用的指针设置为NULL并检查它。如果您在malloced结构中有未使用的字段,这将为您提供一种保证的方式。一个简单的规则是,无论何时释放需要以上述方式检查的指针,只需将其设置为NULL,并使用if = = NULL替换isFree()。这样就不需要跟踪引用计数,并且您确定指针是否有效并且没有指向垃圾。

答案 1 :(得分:5)

不,没有办法。

但是,您可以按如下方式使用一些代码规则:

总是始终 始终使用malloc保护分配:

void * vp;
if((vp = malloc(SIZE))==NULL){
   /* do something dreadful here to respond to the out of mem */
   exit(-1);
}

释放指针后,将其设置为0

free(vp); vp = (void*)0;
/* I like to put them on one line and think of them as one peration */

你想要使用“已释放”功能的任何地方,只需说明

if(vp == NULL)[
    /* it's been freed already */
}

更新

@Jesus在评论中说:

  

我不能真的推荐这个,因为只要你完成了   内存指针应立即超出范围(或至少在   释放它的函数的结尾)这些悬空指针   存在只是不适合我。

这在可能的情况下通常是好的做法;问题是在C的现实生活中往往是不可能的。以一个包含双向链接列表的文本编辑器为例。这个清单很简单:

struct line {
    struct line * prev;
    struct line * next;
    char * contents;
}

我定义了一个分配内存的guarded_malloc函数

void * guarded_malloc(size_t sz){
    return (malloc(sz)) ? : exit(-1); /* cute, eh? */
}

并使用newLine()

创建列表节点
struct line * newLine(){
    struct line * lp;
    lp = (struct line *) guarded_malloc(sizeof(struct line));
    lp->prev = lp->next = lp-contents = NULL ;
    return lp;
}

我将字符串s中的文字添加到我的行

lp->contents = guarded_malloc(strlen(s)+1);
strcpy(lp->contents,s);

并且不要狡辩我应该使用有界长度的形式,这只是一个例子。

现在,如何在释放后删除我在line范围之外创建的char * contents内容?

答案 2 :(得分:3)

我看到没有人解决为什么你想要什么从根本上是不可能的原因。释放资源(在这种情况下是内存,但基本上适用于任何资源)意味着将其返回到可供重用的资源池。系统能够提供合理答案的唯一方法是“地址X的内存块是否已被释放?”是为了防止这个地址被重复使用,并在其中存储一个状态标志,指示它是否“被释放”。但在这种情况下,它实际上并未被释放,因为它无法重复使用。

正如其他人所说,你试图回答这个问题的事实意味着你需要解决基本的设计错误。

答案 3 :(得分:1)

对于特定于平台的解决方案,您可能对Win32函数IsBadReadPtr(以及其他类似函数)感兴趣。此函数将能够(几乎)预测从特定内存块读取时是否会出现分段错误。

注意:Microsoft已弃用IsBadReadPtr。

但是,在一般情况下,这并不能保护您,因为操作系统对C运行时堆管理器一无所知,并且如果调用者传入的缓冲区没有您期望的那么大,那么其余的从操作系统的角度来看,堆块将继续可读。

指针除了指出的地方外没有任何信息。您可以做的最好的事情是“我知道这个特定的编译器版本如何分配内存,所以我将取消引用内存,将指针移回4个字节,检查大小,确保它匹配......”等等。您无法以标准方式执行此操作,因为内存分配是实现定义的。更不用说他们可能根本没有动态分配它。

另外,我建议您阅读Steve McGuire撰写的“Writing Solid Code”。关于内存管理的优秀部分。

答案 4 :(得分:0)