0


我正在实现一个堆分配器(malloc),我需要选择一个幻数来检查给定的指针是否指向我分配的数据结构。对我来说,显然没有任何幻数可以被认为是完全安全的(如果检查了这个数字,我可以确定指向我的数据结构之一),但也许我错过了一些东西,所以......如果有人可以帮助和把我梦想的数量带给我,我真的很感激。提前谢谢。

4

4 回答 4

1

这取决于你这样做是为了什么。如果您这样做是为了尝试捕捉编程错误(例如,您想确保不会意外混淆my_malloc/my_freemalloc/ free),那么只需选择一个随机值。当然,有时它无法检测到这种情况,但这并不重要。它不应该发生。所以在这里:

#define MAGIC_32BIT 0x77A5844CU
#define MAGIC_64BIT 0xD221A6BE96E04673UL

如果正确性取决于此,那么您确实应该以另一种方式执行此操作。例如,通过跟踪您在散列或树中分配的地址,或者在特殊情况下,在位图中分配地址。

如果您实际上正在实现 malloc/free(例如,编写自己的 C 库),请记住,freemalloc编辑的内容(NULL 除外)是标准未定义的行为,因此您的代码不需要担心会发生什么。

于 2011-02-15T19:15:21.933 回答
0

而不是选择一个单一的幻数,您应该使用一个随机数(最好设置至少一个低 8 位 - 例如,您可以通过 ORing in 1 来强制执行此操作)或一些常数 - 您的选择,然后与地址(例如,您正在检查的地址)进行异或 (^)。这种方法将大大降低意外碰撞的几率。

例如,当您编写对象头(或页头,取决于您正在编写的分配器的类型)时,存储MAGIC ^ addr. 现在,当您想检查是否addr有效时,只需查看是否value == addr ^ MAGIC(当然,使用适当的演员表)。

顺便说一句,在开始创建自己的自定义内存分配器之前,请阅读 OOPSLA 2002 中的这篇论文(重新考虑自定义内存分配,Berger、Zorn 和 McKinley 着)。

http://www.cs.umass.edu/~emery/pubs/berger-oopsla2002.pdf

抽象的: 希望实现性能改进的程序员经常使用自定义内存分配器。这项深入研究检查了八个使用自定义分配器的应用程序。令人惊讶的是,对于其中六个应用程序,最先进的通用分配器(Lea 分配器)的性能与自定义分配器一样好或更好。这两个例外使用区域,它们提供更高的性能(提高高达 44%)。区域还减轻了程序员的负担并消除了内存泄漏的来源。然而,我们表明,程序员无法释放区域内的单个对象会导致内存消耗大幅增加。更糟糕的是,这种限制排除了对常见编程习惯使用区域的使用,从而降低了它们的实用性。我们提出了通用和基于区域的分配器的概括,我们称之为收获。Reap 是区域和堆的组合,通过添加单个对象删除提供全方位的区域语义。我们展示了我们的 reaps 实现提供了高性能,优于其他具有类似区域语义的分配器。然后,我们使用案例研究来展示在实践中收获的空间优势和软件工程优势。我们的结果表明,需要快速区域的程序员应该使用 reap,而大多数考虑自定义分配器的程序员应该使用 Lea 分配器。优于其他具有类似区域语义的分配器。然后,我们使用案例研究来展示在实践中收获的空间优势和软件工程优势。我们的结果表明,需要快速区域的程序员应该使用 reap,而大多数考虑自定义分配器的程序员应该使用 Lea 分配器。优于其他具有类似区域语义的分配器。然后,我们使用案例研究来展示在实践中收获的空间优势和软件工程优势。我们的结果表明,需要快速区域的程序员应该使用 reap,而大多数考虑自定义分配器的程序员应该使用 Lea 分配器。

于 2011-02-15T19:34:08.467 回答
0

TALLOC_MAGIC 0xe814ec70

这是来自talloc.c源代码中的文件here。当然,您将不得不看看为什么talloc 选择了这个神奇的数字,但这只是一个开始。

于 2011-02-15T19:07:28.383 回答
0

我没有做过这样的事情(我使用堆但我没有实现任何分配器)而且我不确定你想要做什么,但也许这是你应该使用散列的情况。

根据您正在做什么,这意味着对内存块的地址或其中包含的数据进行散列(每次更改某些内容时,这意味着重新计算散列)或某种内存操作的 ID。

同样,我不确定您要达到的目标,那是我的 2 美分。

于 2011-02-15T18:56:26.063 回答