【问题标题】:How to check if a pointer is valid in C++?如何检查指针在 C++ 中是否有效?
【发布时间】:2016-05-25 02:05:18
【问题描述】:

我收到了一个面试问题,要写一个内存管理器(内存池)。我快完成了,但我在解除分配方面遇到了问题。寻求帮助也很好,就像我们提到帮助的来源一样。所以请帮帮我

int main(void)
{
  using namespace PoolOfMemory;

  initializePoolOfMemory(); // Initialize a char array as the memory pool

  long* int_pointer;

  int_pointer = (long *) allocate(sizeof(long)); //allocate is defined in PoolOfMemory and it returns void*.

  int_pointer = 0xDEADBEEF;

  deallocate(int_pointer);
}

现在我的问题是,当“deallocate”尝试释放 int_pointer 时,它会引发访问冲突错误,显然是因为我正在尝试访问 0xDEADBEEF。下面是我的简单释放函数:

void deallocate(void* p)
{
    Header* start = (Header*)((char*)p-sizeof(Header));
    start->free=true; //This is where I get access violation.;
}

我怎样才能避免这种情况?根据我在网上阅读的内容,我假设检查 p 是否在我的数组中是行不通的。

【问题讨论】:

  • 显而易见的答案是不要操纵指针直接指向的内存位置的值......我无法想象你为什么要分配内存然后以这种方式指向某个任意位置。除非您使用第三方库进行内存管理,该库专门用于防止您释放不在它分配的区域中的指针(这会增加相当多的开销),否则您必须简单地遵循良好的指针规则并编写干净的代码.
  • 我明白你的意思。但是主文件给了我,显然他们希望代码能够处理这种情况。

标签: c++ memory-management access-violation void-pointers


【解决方案1】:

内存管理器确实倾向于更接近硬件级别,并且可能需要根据所使用的操作系统和 CPU 类型做出决策。

在这种情况下,您也许可以证明违反某些 C++ 抽象机器规则是合理的。例如,继续将指针与池数组的边界进行比较。是的,这在使用分段内存或可以形成陷阱指针的体系结构上可能会出错,但是您还要做什么?

之后,为了验证你有一个正确的指针,你可以让你的分配器将一个魔法值写入分配头块,你可以在开始写入空闲布尔值和空闲块指针等之前在 deallocate 函数中验证它.

【讨论】:

  • 谢谢@Zan。使用幻数对我来说听起来不错,但我很困惑如何做到这一点。假设在分配中,我在每个标题的开头设置了一个幻数。当我传递了一个无效指针时,我如何检查它是否指向我的幻数?如果我尝试访问该无效指针,我将收到访问冲突错误。还是我傻?! :-/
  • @Sasan:首先计算指向您的标头的指针。将其转换为char*uintptr_t。然后将该指针与池数组的边界进行比较。一旦你知道它在数组中,你就知道它是安全的,你可以寻找这个幻数。
  • 非常感谢。我实现了它,它有效。至少在我的机器上 :)
猜你喜欢
  • 2010-11-02
  • 2015-12-29
  • 1970-01-01
  • 1970-01-01
  • 2012-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多