如何在iOS上检查指针是否指向堆内存或栈内存?

5
这是另一个问题的类比。无论如何,我正在寻找一种特定于iOS平台的方法来完成这项任务。
为Apple平台开发意味着非基于Apple的工具集通常不适用。因此,我希望找到本地平台的方法来解决这个问题。因为简单的Google搜索给了我this(heap command),我相信也有API函数可以实现这个功能。
我只是在寻找调试构建断言的情况下检测删除堆栈分配对象的情况。因此,只需知道地址指向哪里-堆栈或堆即可。因此,性能、版本兼容性、内部API或任何质量问题都不重要。(也许在模拟器上进行测试也是一个选择)但是我认为如果堆栈完全与堆分离,这不是一个很重的操作。
我标记了C ++,但如果从C ++中适用,则其他任何语言的API也可以。

1
可能是重复问题:https://dev59.com/vmMm5IYBdhLWcg3wKsnO - Borgleader
@Borgleader 我写这个问题是因为没有一种通用的方法可以做到这一点,但特定于平台的方法可能存在。我看到有几个人提到了适用于 MS Windows 的特定 API,但尚未有适用于 iOS 的 API。 - eonil
1
检查Mats Petersson的答案,它可能对你有用。 - Borgleader
1
@Eonil:我刚刚添加了一个简短的章节,介绍如何查找堆栈的范围。 - Mats Petersson
1
你的代码可能存在设计问题。当在堆栈上“分配”对象时,应该使用自定义分配器。这样,你甚至不会遇到你试图检查的那些问题。 - CouchDeveloper
显示剩余7条评论
1个回答

1
如果您在iOS上使用GNU GCC编译器和glibc,那么我认为您可以使用mprobe()函数-如果失败,则该内存块可能已损坏或为堆栈内存块。

http://www.gnu.org/software/libc/manual/html_node/Heap-Consistency-Checking.html

使用可移植的操作系统堆检测更新帖子:

否则,您可以通过覆盖new()和delete()来创建自己的堆内存管理器,记录所有堆内存分配/释放,然后添加您自己的堆检测函数;以下是示例:

// Untested pseudo code follows:
//
#include <mutex>
#include <map>
#include <iostream>

std::mutex g_i_mutex;
std::map<size_t, void*> heapList;

void main()
{
   char var1[] = "Hello";
   char *var2 = new char[5];

   if (IsHeapBlock(&var1))
      std::cout "var1 is allocated on the heap";
   else
      std::cout "var1 is allocated on the stack";

   if (IsHeapBlock(var2))
      std::cout "var2 is allocated on the heap";
   else
      std::cout "var2 is allocated on the stack";

   delete [] var2;
}

// Register heap block and call then malloc(size)
void *operator new(size_t size) 
{
   std::lock_guard<std::mutex> lock(g_i_mutex);
   void *blk = malloc(size);
   heapList.Add((size_t)blk, blk);
   return blk;
}

// Free memory block
void operator delete(void *p)
{
   std::lock_guard<std::mutex> lock(g_i_mutex);
   heapList.erase((size_t)p);
   free(p);
}

// Returns True if p points to the start of a heap memory block or False if p
// is a Stack memory block or non-allocated memory
bool IsHeapBlock(void *p)
{
   std::lock_guard<std::mutex> lock(g_i_mutex);
   return heapList.find((size_t)p) != heapList.end();
}

void *operator new[] (size_t size)
{
   return operator new(size);
}

void operator delete[] (void * p)
{
   operator delete(p);
}

你应该将long改为size_t,因为在win64上long是4个字节,这可能会导致冲突。 - Thomas
@Thomas1125 现在已更改为 size_t。 - user152949

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接