检查指针是否指向堆上已分配的内存

我想知道指针是否指向一个用malloc / new分配的内存。 我意识到任意地址的答案是“不,你不能”,但我认为可以覆盖malloc / free并跟踪分配的内存范围。

您是否知道提供此特定工具的内存管理库?
你知道生产代码的东西吗?

Valgrind很棒,但是仪表太多了(慢)并且Will说我们不想像这样使用Valgrind(使软碰撞变得足够好)。
Mudflap是一个非常好的解决方案,但是专门用于GCC,遗憾的是,检查不会简单地返回布尔值(请参阅下面的答案)。
请注意,检查内存写入是否合法是一个安全问题 。 所以寻找表现是有动力的。

没有标准的方法可以做到这一点,但各种malloc调试工具可能有办法做到这一点。 例如,如果您使用valgrind ,则可以使用VALGRIND_CHECK_MEM_IS_ADDRESSABLE来检查此相关内容

certificate它可能无法有效完成:

 char * p1 = malloc(1); free( p1 ); char * p2 = malloc(1); // probably allocates same block as first malloc 

现在p1和p2都指向堆上的相同内存,但只有p2有效。

如果性能不是您的应用程序的真正问题,您可以自己执行此操作:

定义MyMalloc(…)和MyFree(…),其中,与调用malloc / free一起,更新(有序)对的列表{address – malloc的结果,blockSize – 请求的内存的amt }。 然后当你需要检查指针p时,你会找到一对满足:address <= p <= address + blockSize。

可以/应该检查其他条件,如果你想实际使用那个指针,这只会告诉你地址是否正在使用。

Mudflap (对于gcc)似乎很甜蜜。 你必须编译你的软件,但它会检查任何错误的指针访问(堆/堆栈/静态)。 它被设计用于生产代码,减速估计在x1.5到x5之间。 您还可以禁用读取访问时的检查以获得加速。
用户检查可以使用

 void __mf_check (void *ptr, __mf_size_t sz, int type, const char *location) 

调用此函数会导致:no,fork to gdb,segv或abort,具体取决于环境参数。

您可以使用LD_PRELOAD,并将malloc包装在您自己的函数中。

请参阅我们的CheckPointer工具,该工具将检查每个指针访问的有效性。 它不是特别快,但它会捕获甚至Valgrind都不会捕获的错误(例如,指向解除分配的堆栈帧的指针等)

这个问题的另一个答案显示了对指针有效性进行纯内存范围检查无法检测到问题的情况。 他是对的,因为如果只有内存范围地址,则无法可靠地检查重新分配的存储块是否被滥用。 这称为时间错误。 通过将分配事件与内存块以及范围相关联,您可以检测到这一点。 Checkpointer执行此操作,并将检测错误。

内存分配具有(虚拟)地址和长度。

指针只包含地址。

如果单独跟踪长度,可以检查其包含的长度,例如:

 int check_contained(const char* src,size_t srclen,const char* sub,size_t sublen) { return (sub >= src) && (sub+sublen < src+srclen); } 

Symbian有一个AllocLen函数,但没有POSIX和win32等价物。

我做了类似的事情,但不记得它是如何编码的,我手头没有代码。

但基本思想是覆盖基类的newdelete 。 在new的静态标志设置(例如bool inDynamicAlloc=true )。 在基类的构造函数中询问此标志。 如果是,则对象在堆上分配,否则在堆栈上。

构造函数之后重置标志。

希望这可以帮助。

您可以使用保守垃圾收集器使用的相同技术来确定类似指针的对象是否指向堆。 事实上,您可能会从bdwgc本身获取源代码。 这将是一项非常重要的任务,但它可以根据需要控制和移植。 (事实上​​,大部分移植工作已经完成。)

您可以通过在malloc/malloc.h调用malloc_size(my_ptr)来返回malloc为您的指针分配的大小,如果未分配指针则返回0。 请记住,malloc会调整已分配块的大小,以确保可以从该指针取消引用最具限制性的类型变量并对齐内存。 因此,如果调用malloc(1)(以及malloc(0)),malloc实际上返回16个字节(在大多数机器上),因为最严格的类型具有16个字节的大小