检查指针是否指向堆上分配的内存
我想知道指针是否指向使用malloc/new分配的一段内存。我意识到任意地址的答案是“不,你不能”,但我认为可以覆盖malloc/free并跟踪分配的内存范围。检查指针是否指向堆上分配的内存
您是否知道提供此特定工具的内存管理库?
你知道生产代码的东西吗?
Valgrind很好,但它太多了(仪表慢),并且Will说我们不想使用Valgrind这样(使软件崩溃足够好)。
Mudflap是一个非常好的解决方案,但专用于GCC,可悲的是,检查不会简单地返回布尔值(请参阅下面的答案)。
请注意,检查内存写入是否合法是security issue。因此寻找表现是出于动机。
样张,它可能不能有效地完成:
char * p1 = malloc(1);
free(p1);
char * p2 = malloc(1); // probably allocates same block as first malloc
现在无论p1与上堆相同的内存P2点,但只有P2是有效的。
从哲学上讲,它可能会令人失望,但如果它结束了p2指向与p1相同的地址,p1仍然是可修改内存的地址。所以这对我来说很好。 – log0 2010-06-17 20:08:38
@即使C和C++标准都声称p1不能用于访问该内存? – 2010-06-17 20:15:00
Weeeeel也许p2是p1的地址...取决于你的malloc是如何工作的(在valgrind下运行几乎可以保证'p2!= p1'这是故意的,所以你可以在free后检测到使用,但是malloc仍然可以或者可能不(它们中的一些维持一定大小的最近free'd对象的FIFO队列,它们不会返回p1 ...)) – Spudd86 2010-06-17 20:17:49
您可以使用LD_PRELOAD,并将malloc包装在您自己的函数中。
内存分配具有(虚拟)地址和长度。
指针只包含地址。
如果单独跟踪的长度,你可以检查其包含,例如:
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。
您能否更新链接到AllocLen?它接近死亡:/ – 2015-05-30 21:58:42
@MateuszPiotrowski Symbian已经死了,现在看起来好像是文件:( – Will 2015-06-01 07:09:29
你可以自己做,如果性能是不是为您的应用程序一个真正的问题:
定义MyMalloc(...)和MyFree(...),其中,与调用malloc /*一起,你更新一个(有序的)对列表{地址 - malloc的结果,blockSize - 请求的内存量}。然后,当您需要检查指针p时,您会看到一对满足:地址< = p < =地址+块大小。
其他条件可以/应该检查,如果你想实际使用该指针,这只会告诉如果一个地址正在使用或不。
我做了类似的事情,但不记得它是如何编码的,我手上没有代码。
但基本的想法是覆盖基类的new
和delete
。在new
中设置了静态标志(例如bool inDynamicAlloc=true
)。这个标志在基类的构造函数中被质疑。 当它为真时,该对象被分配到堆上,否则在堆上分配。
构造函数随后重置标志。
希望这会有所帮助。
Mudflap(对于gcc)看起来很甜蜜。你必须编译你的软件,但它会检查任何错误的指针访问(堆/堆栈/静态)。它被设计用于生产代码,估计速度在x1.5到x5之间。您也可以在读访问时禁用检查以加速。什么都没有,叉广发行,SEGV或者根据环境参数中止:
用户检查可使用
void __mf_check (void *ptr, __mf_size_t sz, int type, const char *location)
调用此函数的结果进行。
您可以使用与conservative garbage collector相同的技术来确定指针状对象是否指向堆。事实上,你可能会从bdwgc本身获取源代码。这将是一项不重要的任务,但它可以根据需要控制和移植。 (事实上,大部分移植工作已经完成)。
请参阅我们的CheckPointer工具,它将检查每个指针访问的有效性。它不是特别快,但它会捕获即使Valgrind不会捕获的错误(例如指向已释放栈帧的指针等)
Another answer to this question显示了对指针有效性进行纯内存范围检查将无法检测到问题的情况。他是对的,因为如果只有内存范围地址,就无法可靠地检查重新分配的存储块是否被滥用。这被称为时间错误。通过将分配事件与内存块以及范围相关联,您可以检测到这一点。 Checkpointer会这样做,并会检测到错误。
您可以通过调用malloc_size(my_ptr)
,malloc/malloc.h
它返回malloc为您的指针分配的大小,如果指针未分配,则返回0。请记住,malloc会调整分配区块的大小,以确保可以从该指针取消引用最具限制性的类型变量并对齐内存。因此,如果你调用malloc(1)(以及malloc(0)),malloc实际上会返回16字节(在大多数机器上),因为最具限制性的类型的大小为16字节
+1,这是关键问题需要测试POD内存(即没有构造函数和析构函数)是否正确分配和释放。我猜C++库在堆管理机制中有答案,因为它需要跟踪分配的内存块及其大小。但我不知道它是否公开这些数据(如果没有,是否可能侵入获取数据) - 我正在寻找答案。 – 2015-01-28 08:47:22
你为什么需要它?知道指针是否有效,或者知道它是否是堆指针? – 2016-08-25 10:05:48