如何知道对象变量所指的对象是否存在?
如何知道一个指针对应的内存否被占用?
例如:
p := TObject.Create;
p2 := p;
if NeedFree then
FreeAndNil(p);
if IsTheAddressUsed(p2) then
ShowMessage('p2所指的对象实例还没有被释放')
else
ShowMessage('p2所指的对象实例还没有被释放');
请问函数IsTheAddressUsed(p2)要如何实现?谢谢!或者
var 
  pi, ph : Pinteger;
begin
  New(pi);
  ph := pi;
  Dispose(pi);
  if IsTheAddressUsed(ph) then
    ShowMessage('ph所指的对象实例还没有被释放')
  else
    ShowMessage('ph所指的对象实例还没有被释放');
  
end;

解决方案 »

  1.   

    不太懂
    不过动态分配内存就不用管用不用了
    直接GetMem跟FreeMem不行吗?
      

  2.   

    一个对象实例可以有多个引用,比如:
    var
      a, b: TPerson;
    begin
      a := TPerson.Create;
      b := a;        // b和a指向了同一块内存
      FreeAndNil(a); // 内存已被释放,这时候如果再操作b将导致非法操作
    end;
      

  3.   

    LZ的代码,P和P2指向同一内存区域,当P被释放时,P2亦无效了。再引用P2会出现非法操作的。
      

  4.   

    try
      something;
    except on E:内存地址非法访问 do
      

  5.   

    谢谢您们,我现在也没有实用的东西要处理。只是好奇,很想知道答案。因为我认为Windows是能判断的,否则它分配内存的时候就不会正好只分配那些没有占用的内存,现在问题是Windows会不会留一个接口(API),让我们也访问一下哪些内存是否为空闲的。以下是我听说的:
    “malloc()到底从哪里得到了内存空间?答案是从堆里面获得空间。也就是说函数返回的指针是指向堆里面的一块内存。操作系统中有一个记录空闲内存地址的链表。当操作系统收到程序的申请时,就会遍历该链表,然后就寻找第一个空间大于所申请空间的堆结点,然后就将该结点从空闲结点链表中删除,并将该结点的空间分配给程序。就是这样!”
    windows让不让我访问这样的空闲结点链表,如果不让的话,有没有提供这样的API: IsTheAddressUsed(lpPtr  ph,[int Size]);第一个参数是一个指针。
    盼望高手给一个明确的答案,否则我就吃不香睡不好,当然我也努力去找答案,如果找到了答案也会告诉大家。
      

  6.   

    windows本身不提供这种判断,传统上是谁申请谁释放java、.net这些平台都是通过在程序和windows之间增加一个VM,
    VM是可以知道内存是否被使用的
      

  7.   

    sdzeng ,多谢了。首先你让我明确了,不是通过调用一个windows的API就能判断的,其次诸如VM这样的神秘人物能够满足我的愿望,只是我还不认识它,再次,我还是要广交朋友,多认识一些伟大人物,否则为人不识陈近南,纵称英雄也枉然。
      

  8.   

    首先, 内存管理分为两个层次, 一个是操作系统管理的部分, 一个是Delphi管理的部分操作系统管理的部分, 操作系统提供了相应的API, 如: LocalAlloc、LocalReAlloc、LocalFree、GlobalAlloc、GlobalReAlloc、GlobalFree、VirtualAlloc、VirtualReAlloc、VirtualFree、HeapAlloc、HeapReAlloc、HeapFree等。如果程序全用操作系统提供的内存管理,那对于大量的小内存申请和释放操作,其性能会非常低,所以,Delphi也提供内存管理,大量的小内存的申请和释放,其转化为对操作系统的少量大内存块的申请和释放,以提高性能。则楼主所说的所指的对象,可能有两种情况:
    1. Delphi的内存管理器释放此对象内存时, 发现此内存块所在的整个大块都已经没有内存被使用, 则向操作系统释放了整个大内存块。
    2. Delphi的内存管理器释放此对象内存时, 发现此内存块所在的整个大块还有内存正被使用,其只是在自己的内存管理器中标识此内存已经被释放。对于以上两种情况,其分别对应:
    1. Delphi内存管理器认为此内存无效,操作系统的内存管理器也认为此内存无效。
    2. Delphi内存管理器认为此内存无效,操作系统的内存管理器却认为此内存有效。对于操作系统而言,有以下API能够用于判断内存是否有效:IsBadCodePtr、IsBadReadPtr、IsBadWritePtr对于Delphi内存管理器来说,其内存管理器是可以指定的,但Delphi提供缺省的内存管理器。
    Delphi提供的缺省的内存管理器,并未提供完成楼主所需功能的函数。要完成楼主的功能,有两种方法:
    1. 楼主可以根据Delphi提供的缺省内存管理器的源码,自己写所需的函数。但不同版本的Delphi提供的缺省的内存管理器有一定区别。如老版本的Delphi提供的缺省的内存管理器性能就比较差,相比之下内存占用比较多,性能比较差,自Delphi 2006之后,其参考FastMM,有相当大的改善。(如:Delphi 2007的缺省内存管理器的源码位于源文件 getmem.inc )
    2. 或楼主可以使用自己所写的内存管理器。 如:MemoryManager.GetMem, MemoryManager.AllocMem 直接调用LocalAlloc, MemoryManager.ReallocMem直接调用 LocalReAlloc, MemoryManager.FreeMem直接调用LocalFree。则直接使用IsBadWritePtr就可以完成楼主所要求的功能。当然,这个简单的内存管理器性能很差。
      

  9.   

    谢谢!十分感谢谢!
     
    再请问:一个进程结束后,delphi程序员没有将一小块内存(例如New(pi : PInteger 分配的内存,姑且称为IM)释放,IM所在的大内存(且称为BIM)。结果会不会造成内存泄漏,如果会,是只有IM泄漏还是连BIM都泄漏了?
      

  10.   

    对不起,上一贴有笔误。
    重新请问:
    一个进程结束后,delphi程序员没有将一小块内存(例如New(pi:PInteger)分配的内存)释放,(将这个小内存姑且称为IM,IM所在的大内存称为BIM)。结果会不会造成内存泄漏,如果会,是只有IM泄漏还是连BIM都泄漏了?
      

  11.   

    进程结束时, Delphi 缺省内存管理器会释放其所以分配的内存, 所以, 你用new分配的内存, 在进程结束后, Delphi 缺省内存管理器已经帮你释放了内存另: 操作系统的内存管理模块, 也会帮你释放这部分内存, 例如: 你程序分配了一大块内存, 然后强制结束进程, 此部分内存操作系统还是会回收的.对于能够跨进程使用的内存(如GlobalAlloc分配的内存), 如果没释放, 则进程结束时, 操作系统不会自动回收.
      

  12.   

    如何知道对象变量所指的对象是否存在? 
    如何知道一个指针对应的内存否被占用?VAR P:POINTER;
        A:TLEBEAL;
    BEGIN
      IF A = NILL THEN 
        A := A.TLEABEL.CREATE;  IF ASSIGNED(P)THEN 
        P:= .......
     
    END;