本文介绍了如何确定是否返回的指针是栈或堆在的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个插件架构,在那里我调用函数在一个动态库,他们还给我一个的char * 这就是答案,但在以后的阶段中。

I have a plugin architecture, where I call functions in a dynamic library and they return me a char* which is the answer, it is used at some later stage.

这是一个插件功能的签名:

This is the signature of a plugin function:

char* execute(ALLOCATION_BEHAVIOR* free_returned_value, unsigned int* length);

其中, ALLOCATION_BEHAVIOR 必须是: DO_NOT_FREE_ME FREE_ME DELETE_ME 其中插件(库)告诉我的插件如何分配它刚刚返回的字符串: DO_NOT_FREE_ME 告诉我,这是我不应该碰(如静态常量的char * 从不改变) FREE_ME 告诉我,我应该使用免费()来释放返回值, DELETE_ME 告诉我使用删除[] 摆脱了内存泄漏。

where ALLOCATION_BEHAVIOR must be either: DO_NOT_FREE_ME, FREE_ME, DELETE_ME where the plugin (in the library) tells me how the plugin allocated the string it has just returned: DO_NOT_FREE_ME tells me, this is a variable I'm not supposed to touch (such as a const static char* which never changes) FREE_ME tells me I should use free() to free the returned value and DELETE_ME tells me to use delete[] to get rid of the memory leaks.

显然,我不信任插件,所以我想能够检查,如果他告诉我免费()变量,的确是东西,才能真正被释放......这可能使用今天的C / C ++在Linux / Windows的技术?

Obviously, I don't trust the plugins, so I would like to be able to check that if he tells me to free() the variable, indeed it is something that can really be freed ... Is this possible using todays' C/C++ technology on Linux/Windows?

推荐答案

之辨的malloc /免费新建/删除一般是不可能的,至少不能以可靠的和/或移植的方法。更使只是wrapps 的malloc 反正在很多的实现。

Distinguishing between malloc/free and new/delete is generally not possible, at least not in a reliable and/or portable way. Even more so as new simply wrapps malloc anyway in many implementations.

以下替代无区别堆/堆栈已经过测试,但他们的的各项工作。

None of the following alternatives to distinguish heap/stack have been tested, but they should all work.

Linux的:


  1. 由Luca Tettananti提出的解决方案,解析的/ proc /自/图来获取堆栈的地址范围。

  2. 如在启动的第一件事,克隆你的进程,这意味着的提供的堆栈。既然你提供,你会自动知道它在哪里。

  3. 呼叫GCC的 __ builtin_frame_address 函数随的级别的参数,直到它返回0。后来才知道深浅。现在叫 __ builtin_frame_address 再次与最高水平,并一度以0凡是住在栈上必然是这两个地址之间的水平。

  4. SBRK(0)作为启动的第一件事,记住该值。每当你想知道如果事情是在堆上, SBRK(0)再次 - 这就是堆上必须在两个值之间。请注意,这不会与使用内存映射大的分配分配器可靠地工作。

  1. Solution proposed by Luca Tettananti, parse /proc/self/maps to get the address range of the stack.
  2. As the first thing at startup, clone your process, this implies supplying a stack. Since you supply it, you automatically know where it is.
  3. Call GCC's __builtin_frame_address function with increasing level parameter until it returns 0. You then know the depth. Now call __builtin_frame_address again with the maximum level, and once with a level of 0. Anything that lives on the stack must necessarily be between these two addresses.
  4. sbrk(0) as the first thing at startup, and remember the value. Whenever you want to know if something is on the heap, sbrk(0) again -- something that's on the heap must be between the two values. Note that this will not work reliably with allocators that use memory mapping for large allocations.

知道堆栈的位置和大小(替代图1和2),是微不足道的查出地址是在该范围内。如果不是的话,就一定是堆(除非有人试图成为超级智能的屁股,给你一个指针指向一个静态全局或函数指针,或这样......)。

Knowing the location and size of the stack (alternatives 1 and 2), it's trivial to find out if an address is within that range. If it's not, is necessarily "heap" (unless someone tries to be super smart-ass and gives you a pointer to a static global, or a function pointer, or such...).

Windows系统:


  1. 使用CaptureStackBackTrace,任何生活在堆栈上必须返回指针数组的第一个和最后一个元素之间。

  2. 使用GCC-MinGW的(和 __ builtin_frame_address ,这应该只是工作)同上。

  3. 使用 GetProcessHeaps HeapWalk 来检查匹配每一个分配的块。如果没有匹配没有一个堆,它因此在栈中分配(...或内存映射,如果有人试图成为超级智能和你)。

  4. 使用 HEA $ P $的palloc HEAP_REALLOC_IN_PLACE_ONLY 和尺寸完全相同。如果失败,该内存块以指定的地址没有被分配在堆上。如果成功,这是一个空操作。

  5. 使用 GetCurrentThreadStackLimits (于Windows 8/2012年仅)

  6. 呼叫 NtCurrentTeb()(或读 FS:[18小时] ),并使用领域返回TEB的StackBase StackLimit

  1. Use CaptureStackBackTrace, anything living on the stack must be between the returned pointer array's first and last element.
  2. Use GCC-MinGW (and __builtin_frame_address, which should just work) as above.
  3. Use GetProcessHeaps and HeapWalk to check every allocated block for a match. If none match for none of the heaps, it's consequently allocated on the stack (... or a memory mapping, if someone tries to be super-smart with you).
  4. Use HeapReAlloc with HEAP_REALLOC_IN_PLACE_ONLY and with exactly the same size. If this fails, the memory block starting at the given address is not allocated on the heap. If it "succeeds", it is a no-op.
  5. Use GetCurrentThreadStackLimits (Windows 8 / 2012 only)
  6. Call NtCurrentTeb() (or read fs:[18h]) and use the fields StackBase and StackLimit of the returned TEB.

这篇关于如何确定是否返回的指针是栈或堆在的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-28 15:31