2016-02-14 298 views
1

我已经给了一个面试问题来写一个内存管理器(内存池)。我差不多完成了,但我在解除分配时遇到问题。寻求帮助也很好,就像我们提到帮助的来源一样。所以,请帮我如何检查指针在C++中是否有效?

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); 
} 

现在我的问题是,当“取消分配”试图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是否在我的数组中,是行不通的。

+4

显而易见的答案是不操纵指针直接指向的内存位置的值...我无法想象为什么你会分配内存,然后指向这种方式的任意位置。除非您使用第三方库进行内存管理,这是专门设计用于防止您释放不在其分配的区域内的指针(这会增加相当多的开销),您必须遵循良好的指针规则并编写干净的代码。 –

+0

请参阅http://stackoverflow.com/questions/496034/most-efficient-replacement-for-isbadreadptr和http://stackoverflow.com/questions/17202570/c-is-it-possible-to-determine-whether-一个指针指向一个有效的对象 –

+0

我明白你的观点。但主要文件给了我,显然他们希望代码来处理这种情况。 – Sasan

回答

1

内存管理器倾向于更接近硬件级别,可能需要根据操作系统和CPU类型进行决策。

在这种情况下,您可能有理由打破一些C++抽象机器规则。例如,只需继续并将指针与池数组的边界进行比较即可。是的,在使用分段内存或可以形成陷阱指针的体系结构上,这可能会出错,但您还有什么要做?

之后,要验证您有合适的指针,您可以让分配器向分配标头块中写入一个魔术值,在开始写入自由布尔值和空闲块指针之前,您可以在释放函数中验证该值,等

+0

谢谢@赞。使用神奇的数字听起来不错,但我很困惑如何做到这一点。假设在分配中,我在每个标题的开头设置了一个幻数。当我传递了一个无效指针时,我该如何检查它是否指向我的幻数?如果我尝试访问那个无效指针,我会得到一个访问冲突错误。或者我是愚蠢的?! : -/ – Sasan

+0

@Sasan:首先计算指向头部的指针。将其转换为'char *'或'uintptr_t'。然后将该指针与池数组的边界进行比较。一旦你知道它在数组中,你知道它是安全的阅读,并且你可以查找幻数。 –

+0

非常感谢。我实现了它,它工作。至少在我的机器上:) – Sasan