function IsValidMemPtr(Ptr: Pointer): Boolean;
var
  p: PInteger;
begin
  p := Pointer(Integer(Ptr)-4);
  result := (Cardinal(Ptr) > $FFFF) and not IsBadReadPtr(p, 8) and (p^ and 2 <> 0) and (p^ and $80000000 = 0) and (p^ and $7FFFFFFC <> 0);
end;

解决方案 »

  1.   

    不难理解:
    1. windows中有效pointer指针的值都大于64k
    2. IsBadReadPtr是windows的api, 判断应用程序是否有权限读某个地址和长度的内存
    3. 在1和2满足的情况下说明内存是delphi的memory manager可以访问的,此时可以读取memory manager分配的内存的控制字段以判断该块内存是否有效,该控制字段是一个整数,位于Ptr-4位置,低两位和最高位是标记,剩下的位组成了内存块的长度。最低位标识了memory manager的内存链表中前一块内存是否已释放,最低第二位标识了本块内存是否已占用带注释的代码在这:function IsValidMemPtr(Ptr: Pointer): Boolean;
    var
      p: PInteger;
    begin
      p := Pointer(Integer(Ptr)-4);   // 指向内存控制字段
      result := (Cardinal(Ptr) > $FFFF) and not IsBadReadPtr(p, 8) //至少控制字段及内存前4个字节(delphi动态分配的内存是4字节的整数倍,最少12字节)是有效可访问地址
                and (p^ and 2 <> 0)    // 内存块被占用
                and (p^ and $80000000 = 0)   //未被充填
                and (p^ and $7FFFFFFC <> 0);  // 内存块长度<> 0
    end;这段代码是有使用限制的,不过可以适应90%的应用(尤其是可以判断某个对象是否已释放)。它不能判断指向栈中的指针是否有效,也不能判断指向某块内存中间某个地址的指针是否有效。比如这段代码不能判断如下情况:procedure test;
    var
      buffer: array [0..100] of char;
      p, p1: Pointer;
    begin
      p := @buffer;
      getmem(p1, sizeof(buffer));
      p1 := pointer(integer(p1)+50);
      if IsValidMemPtr(p) then ...   // 错误!无法判断栈中的指针是否有效
      if IsValidMemPtr(p1) then ...  // 错误!不能判断指向某块内存中间的地址是否有效
    end;
      

  2.   

    写得不错,加点分
    我加到FAQ
      

  3.   

    同意aiirii的意见,200分意思一下就行了:)