8

给定一个指向某个变量的指针..有没有办法检查它是静态分配的还是动态分配的?

4

8 回答 8

11

引用您的评论:

我正在制作一个基本上可以摆脱结构的方法。它有一个数据成员,它是指向可能会或可能不会被分配的东西的指针..取决于哪个,我想释放它

正确的方法是在结构中添加另一个成员:指向释放函数的指针。

这不仅仅是静态分配与动态分配。有几种可能的分配器,其中malloc()只是一种。

在类 Unix 系统上,它可能是:

  • 静态变量
  • 在堆栈上
  • 在堆栈上但动态分配(即alloca()
  • 在堆上,分配有malloc()
  • 在堆上,分配有new
  • 在堆上,在分配的数组中间new[]
  • 在堆上,在分配有的结构内malloc()
  • 在堆上,在一个对象的基类中分配有new
  • 分配给mmap
  • 使用自定义分配器分配
  • 更多选项,包括上述几种组合和变体

在 Windows 上,您还有多个运行时、、、LocalAllocGlobalAllocHeapAlloc可以轻松创建多个堆)等等。

您必须始终使用您使用的分配器的正确释放函数来释放内存。因此,负责分配内存的程序部分也应该释放内存,或者您必须将正确的释放函数(或围绕它的包装器)传递给将释放内存的代码。

您还可以通过要求始终使用特定分配器分配指针或通过自己提供分配器(以分配内存的函数和可能释放内存的函数的形式)来避免整个问题。如果您自己提供分配器,您甚至可以使用技巧(如标记指针)来允许也使用静态分配(但我不会在这里详细介绍这种方法)。

Raymond Chen有一篇关于它的博客文章(以 Windows 为中心,但概念在任何地方都是相同的):分配和释放内存跨模块边界

于 2008-11-09T23:36:03.890 回答
2

ACE库无处不在。您也许可以检查他们是如何做到的。一般来说,你可能一开始就不需要这样做......

于 2008-11-09T22:55:37.043 回答
2

由于堆、堆栈和静态数据区通常占用不同范围的内存,因此可以在熟悉进程内存映射的情况下查看地址并确定它位于哪个分配区域。这种技术既是架构和编译器特定的,因此它使您的代码移植更加困难。

于 2008-11-09T23:01:40.307 回答
2

大多数 libc malloc 实现通过在每个返回的内存块之前存储一个标头来工作,该标头具有字段(由 free() 调用使用),其中包含有关块大小的信息以及“魔术”值。这个神奇的值是为了防止用户意外删除未分配的指针(或释放被用户覆盖的块)。它是非常特定于系统的,因此您必须查看 libc 库的实现才能确切了解那里的神奇价值。

一旦你知道了,你将给定的指针移回指向标题,然后检查它的魔法值。

于 2008-11-09T23:10:45.517 回答
0

你能像 malloc 调试器那样使用 LD_PRELOAD 或其他东西连接到 malloc() 本身吗?如果是这样,您可以保留所有已分配指针的表并使用它。否则,我不确定。有没有办法获取malloc的记账信息?

于 2008-11-09T22:52:55.240 回答
0

不作为标准功能。
malloc 库的调试版本可能具有执行此操作的某些功能。

于 2008-11-09T22:58:02.437 回答
0

您可以将其地址与您知道的静态地址进行比较,并说它仅在距离较远时才被分配,如果您知道它应该来自的范围,但如果它的范围未知,您就不能真正相信这一点。

于 2008-11-09T23:01:03.820 回答
-1

1.) 获取您拥有的代码的映射文件。

2.) 底层进程/硬件目标平台应该有一个内存映射文件,它通常指示 - 内存的起始地址(堆栈、堆、global0、该块的大小、该内存块的读写属性。

3.) 从 1.) 中的 mao 文件中获取对象(指针变量)的地址后,尝试查看该地址属于哪个块。你可能会有一些想法。

=广告

于 2008-11-09T23:26:17.043 回答