一个证明它可能无法有用地完成:
char * p1 = malloc(1);
free( p1 );
char * p2 = malloc(1); // probably allocates same block as first malloc
现在p1和p2都指向堆上的同一块内存,但只有p2是有效的。
p2 != p1
,这是有意为之的,以便您可以检测到释放后使用,但好的malloc可能会或可能不会这样做(其中一些维护特定大小的最近释放对象的FIFO队列,它们不会返回p1...))。 - Spudd86目前没有标准方法来实现这个,但是各种内存分配调试工具可能有自己的实现方式。例如,如果你使用valgrind,你可以使用VALGRIND_CHECK_MEM_IS_ADDRESSABLE
来检查它以及相关的事情。
malloc_zone_from_ptr(…)
函数;如果它返回 NULL
,那么该指针并未使用任何变体的 malloc
/calloc
/等分配。这与释放非 malloc 指针时出现的错误信息和 SIGABRT 时使用的相同机制。请参见 Darwin's malloc.c。#include <malloc/malloc.h>
…
int *mallocAllocated = (int *)malloc(16);
int *newAllocated = new int[16];
int stackAllocated[16];
printf("mallocAllocated allocated with malloc: %s\n",
(malloc_zone_from_ptr(mallocAllocated) != NULL) ? "yes" : "no");
printf("newAllocated allocated with malloc: %s\n",
(malloc_zone_from_ptr(newAllocated) != NULL) ? "yes" : "no");
printf("stackAllocated allocated with malloc: %s\n",
(malloc_zone_from_ptr(stackAllocated) != NULL) ? "yes" : "no");
free(mallocAllocated);
free(newAllocated);
free(stackAllocated); // aborts with SIGABRT here
输出:
mallocAllocated allocated with malloc: yes
newAllocated allocated with malloc: yes
stackAllocated allocated with malloc: no
提示:这是否适用于所有Darwin平台和构建版本以及所有类型的内存分配?我不清楚。我所知道的只有源代码和man malloc_zone_from_ptr
。
为什么您要在macOS /«Apple»OS / Darwin系统上特别执行此操作?嗯,如果您在堆栈分配Objective-C对象并且想确保不调用[super dealloc]
到NSObject的实现中,那将是一个比较特殊的用例。
void __mf_check (void *ptr, __mf_size_t sz, int type, const char *location)
内存分配具有(虚拟)地址和长度。
指针仅包含地址。
如果您单独跟踪长度,则可以检查其是否包含,例如:
int check_contained(const char* src,size_t srclen,const char* sub,size_t sublen) {
return (sub >= src) && (sub+sublen < src+srclen);
}
AllocLen
函数,但没有POSIX或win32的等效函数。我做过类似的事情,但是不记得具体的编码方式了,也没有代码在手。
但基本思路是重载一个基类的new
和delete
。在new
中设置一个静态标志(例如bool inDynamicAlloc=true
)。在基类的构造函数中会检查这个标志。
如果它为真,则对象在堆上分配,在栈上则相反。
构造函数之后会重置该标志。
希望这可以帮到你。
您可以使用与保守式垃圾收集器相同的技术来确定指针对象是否指向堆内存。实际上,您可能可以从bdwgc本身中抄袭源代码。这将是一个非微不足道的任务,但这是您可以控制和根据需要移植的内容。(实际上已经完成了大部分移植工作。)