如何检查C中是否已经释放了指针?

mftmpeh8  于 2023-04-11  发布在  其他
关注(0)|答案(9)|浏览(553)

我想检查一个指针是否已经被释放了。我如何使用gnu编译器集来做这件事?

bkhjykvo

bkhjykvo1#

没有可靠的方法来判断指针是否被释放,正如Greg评论的那样,释放的内存可能被其他无关数据占用,你会得到错误的结果。
实际上,没有标准的方法来检查指针是否被释放。* 也就是说 *,glibc确实有函数(mcheckmprobe)来查找指针的malloc状态,以进行堆一致性检查,其中一个是查看指针是否被释放。

不过,这些函数主要用于调试,they are not thread-safe。**如果您不确定需求,请避免使用这些函数。**只要确保您已配对malloc/free即可。

示例http://ideone.com/MDJkj

#include <stdio.h>
#include <stdlib.h>
#include <mcheck.h>

void no_op(enum mcheck_status status) {}

int main()
{
    mcheck(&no_op);

    void* f = malloc(4);

    printf("%d (should be %d)\n", mprobe(f), MCHECK_OK);
    printf("%d (should be %d)\n", mprobe(f), MCHECK_OK);

    free(f);

    printf("%d (should be %d)\n", mprobe(f), MCHECK_FREE);
    printf("%d (should be %d)\n", mprobe(f), MCHECK_FREE);

    return 0;
}
gab6jxml

gab6jxml2#

您可以通过编写一个宏来扩展将NULL赋值给指针值的概念。例如:

#define FREE(ptr) do{ \
    free((ptr));      \
    (ptr) = NULL;     \
  }while(0)

然后只要你确保你的代码只使用FREE()而不是free(),你就可以相当自信地说,你写的代码不会两次释放相同的内存。当然,这并不能阻止多次调用库函数来释放内存。它也不能保证每个malloc都有一个free。
你可以用一个函数来尝试,但它会变得很尖锐,因为你必须抛出一个引用操作符,它看起来不再像是一个正常的free()调用。

tvz2xvvm

tvz2xvvm3#

你没有,因为你不能。
跟踪从malloc()获得的指针,并且只释放这些指针,而且只释放一次。
如果你愿意,内存没有内存,所以它不知道它是否被分配。只有你的操作系统的内存管理器可以告诉你(但C不包括任何标准化的机制来查询此信息)。

41zrol4v

41zrol4v4#

我知道这个答案是a little bit晚了,但我只是读了this answer并写了一些代码来验证以下内容:
Free会将内存块放入自己的空闲块列表中。通常它也会尝试将地址空间中相邻的块合并在一起。空闲块列表只是一个循环的内存块列表,当然在开始时有一些管理数据。free-list也是第一个位置,malloc在需要时查找新的内存块。在从操作系统调用新内存之前会对其进行扫描。当找到大于所需内存的内存块时,它被分成两部分,一部分返回给调用者,另一部分放回空闲列表。
这段代码只检查分配的第一个指针是否被释放:

int is_freed(void *p)
{
    void * q;
    char p_addr [50];
    char q_addr [50];

    sprintf(p_addr, "%p", p);

    q = malloc (1);
    sprintf(q_addr, "%p", q);
    free (q);

    return ! strcmp(q_addr, p_addr);
}

我已经在HP-UX和Linux Redhat上测试了这段代码,对于只有一个指针的情况,它可以工作。

8gsdolmq

8gsdolmq5#

友情提示:如果你在另一个函数中设置了一个指向NULL的指针参数,并希望它影响参数(传入的原始指针),则该函数必须接受指向该指针的指针(双ptr)。
比如说

void cleanup(int *int_ptr) {
  free(int_ptr);
  int_ptr = NULL; // Not working ??
}

int main() {
  int a = 8; 
  int* a_ptr = &a;
  cleanup(a_ptr);
  printf("%p", a_ptr); // Unexpected: Does not print NULL
}

这不符合预期。理由:a_ptr是一个指针,但它实际上只是一个包含值的变量-所包含的值有点特殊,因为它是一个虚拟内存地址,但它仍然是一个值。当这个值传入cleanup时,像任何其他变量一样,cleanup创建该值的本地副本。因此,如果a_ptr的值为0x7ffd86656848int_ptr也会有值0x7ffd86656848。当然,将int_ptr设置为NULL并不会将a_ptr设置为NULL
所以,如果你想设置int_ptr = NULL,你必须传入一个双指针

void cleanup(int **int_ptr) {
  free(*int_ptr);
  *int_ptr = NULL;
}
emeijp43

emeijp436#

编写一个函数来捕获信号SIGABRT

eoigrqb6

eoigrqb67#

我就是这么做的

bool pointer_allocated(void* ptr) {
  return ptr != NULL;
}

编辑:这个答案很错误,所以我会更正

如果你想检查指针是否被释放,你可以在释放指针后将其设置为NULL。

free(ptr);
ptr = NULL;

// You can use ptr != NULL or ptr != 0, its pretty much the same thing
if(ptr) {
    // Pointer is set
} else {
    // Pointer has been freed
}

如果你不打算再次使用指针,你不需要将指针设置为NULL。在这种情况下,没有任何意义,只会浪费CPU时间。

imzjd6km

imzjd6km8#

你不能。跟踪这个的方法是在释放指针后将其分配给0NULL。然而,正如Fred Larson所提到的,这对指向同一位置的其他指针没有任何影响。

int* ptr = (int*)malloc(sizeof(int));
free(ptr);
ptr = NULL;
3b6akqbq

3b6akqbq9#

你不能。只要在你free它之后分配NULL给它,以确保你不会释放它两次(free(NULL)是可以的)。
更好的是,如果可能的话,不要在你“忘记”你已经释放了它的地方编写代码。

编辑

将问题解释为 * 如何找出指针所指向的内存是否已被释放 *:你不能这么做你得自己记账

相关问题