定义了
type
  TZD_Rec = Record
     file_column :string;          
     file_column_order :integer;   
     file_column_value :string;    
     table_name :string;           
     table_column :string;         
  end;
pZD_Rec=^TZD_Rec;然后再一个函数里var 了一个局部变量 a:array of pZD_Rec;
这个函数中间运行的时候,我也SetLength(a,column_count);了

        While not eof do
        begin
           a1:=ADOQuery1.fieldbyname('列名').AsString;
           New(a[i]);
           pZD_Rec(a[i])^.file_column:=a1;
           pZD_Rec(a[i])^.file_column_order:=-1;
           pZD_Rec(a[i])^.table_name:=ADOQuery1.fieldbyname('表名').AsString;
           inc(i);
           next;
        end;
这个函数结束的时候,我也
        for j:=0 to column_count-1 do
        begin
          if a[j]<> nil then
            Dispose(a[j]);
        end;但是我看Dispose没有用啊,比如:我再for j:=0 to column_count-1 do设了个断点,dispose一个指针后,我看刚dispose的那个指针还是没有变成nil,还是有值,这怎么回事啊?有没有人知道,拜托了。

解决方案 »

  1.   

    Dispose只是释放内存的引用,而不会对内存做修改,如果你想让它变为nil那就改为
              if a[j] <> nil then begin 
                Dispose(a[j]); 
                a[j] := nil;
             end;
      

  2.   

    指针自身有个存储地址,和它指向区域的地址
    new(a) 分配的是它指向区域的地址
    dispose(a)释放的也是 指向区域的地址自身的地址依然存在只是你不能引用它指向的区域了否则会出错。
    a:=nil是将自身的地址置空
     
      

  3.   


    to:unsigned
    你说“Dispose只是释放内存的引用,而不会对内存做修改”。那如果我只用了Dispose,而没有   a[j] := nil; 那长时间一直这样开着这个程序,也一直再运行的话,会不会就因为这个内存会变得很大?
      

  4.   

    其实,我也就是想问,如果我没有 a[j] := nil;的话,长时间这样下去,会不会对程序照成影响,因为今天早上去服务器上看的时候,报的memory out的错误。
      

  5.   

    不是可能导致内存不断变大,而是会产生异常,比如你下一次还会到这个Dispose当中执行.另外对于其他位置判断不到a[index]为nil,还会继续操作,就访问了野指针,严重一点,直接就导致应用程序崩溃.
      

  6.   

    不会的你调用的是setlength()程序退出后会自动释放a[j]的
      

  7.   

    在程序出现内存访问错乱之后,任何错误都是有可能的.比如常见的Out of Memory,Invalid Pointer Operation等等.
      

  8.   

    这个和删除文件一样的道理,你dispose,只是释放了这块内存,对应内存的数据并没有被改写.
    删除文件也只是做删除标记,文件的内容还是存在磁盘上,那会不会电脑用久了,就没空间存放文件了呢,显然不是.
      

  9.   

    注意看清楚a:array of pZD_Rec; 这里用的是pZD_Rec而不是TZD_Rec
      

  10.   

    两个问题不是同一级别的.对于文件,系统有一个文件分配表,当你删除之后,在表当中是查不到了的,也就相当于你对a[Index]设置了Nil,至于文件内容没有被改写,就好比你释放内存之后或之前是不需要使用fillchar清空的.
      

  11.   

    我没说清楚,的意思是这样的
        for j:=0 to column_count-1 do 
            begin 
             // if a[j] <> nil then 
                Dispose(a[j]); 
            end;
    应该可以吧? 
      

  12.   

    之所以使用pZD_Rec而不是TZD_Rec 在很多时候,就是不想对所有的都分配完空间,只是想用到几个分配几个.这个时候,如果没有这个if a[j] = nil的判断,那么后果就不好预测了.
      

  13.   

    这个是运行再一个子函数里的。
    局部变量 a:array of pZD_Rec; 
    而且SetLength(a,column_count);

            While not eof do 
            begin 
              a1:=ADOQuery1.fieldbyname('列名').AsString; 
              New(a[i]); 
              pZD_Rec(a[i])^.file_column:=a1; 
              pZD_Rec(a[i])^.file_column_order:=-1; 
              pZD_Rec(a[i])^.table_name:=ADOQuery1.fieldbyname('表名').AsString; 
              inc(i); 
              next; 
            end; 
    都是再这个子函数里运行的,
    再这个子函数运行的最后加的
            for j:=0 to column_count-1 do 
            begin 
              if a[j] <> nil then 
                Dispose(a[j]); 
            end; 所以每次进这个子函数的时候,a都是一个新的吧?
    --------------------------------------------------
    问题2:以前再子函数里用的是a:array of TZD_Rec; 而不是指针数组。网上很多地方说,如果把结构体放到数组里的话,会很占内存的,建议用指针,所以我才改成指针的,不知道指针的效果是不是好些?
      

  14.   

    直接使用结构体,分配的是一块连续的内存.而换用指针的话,实际上本身指针组成了一个数组,还要增加代码来进行检查(=nil)明显后者的消耗更大.用指针,不是让你用指针数组,这是两回事.
    a:pZD_Rec;
    这是一个指针,如果你想要分配N个结构,那就用GetMem之类的分配N个结构的大小即可.一次性分配内存远比分多次分配内存消耗更小.
      

  15.   

    反正是在一个子程序中,setlength也是动态分配内存在堆中,内存够用的话,用TZD_Rec挺好的,省的操作指针。用setlengthdelphi会自动释放的,简单。只是在调用子程序时内存会变大,退出就恢复了,看你的情况了。
      

  16.   

    如果是长时间运行,并且这段子程序也是频繁执行的话,可以分配下来放到TLS当中,或者直接使用ThreadVar声明。这样就只需要申请一次就好了。使用的时候对于不能覆盖到的地址进行初始化操作即可。压根儿就不需要释放。