procedure TForm1.btn1Click(Sender: TObject);
var ptr, ptr2 : ^integer;
  i : integer;
begin
  GetMem(ptr, sizeof(integer) * 20);
    //这句等价于C的 ptr = (int*) malloc(sizeof(int) * 20);
  ptr2 := ptr; //保留原始指针位置
  for i := 0 to 19 do
  begin
    ptr^ := i;
    ShowMessage(IntToStr(ptr^));
    Inc(ptr);
  end;
  FreeMem(ptr2);     //为什么这里释放的是ptr2,我试验了如果是ptr就会报地址引用错误,
  Dec(ptr,20);       //但是上面的代码如  ptr2 := ptr,如果这样赋值,相当于就引用指针地址了,
  for i:=1 to 20 do   //如果ptr2释放了,PTR也应该释放啊,为什么没有释放呢?
  begin
     ShowMessage(IntToStr(ptr^));
     Inc (ptr)     ;
  end
end;
还有我想把赋值的这些数值一个个的showmessage出来,可是我这样写,根本读不出来,不知道是哪边错了,麻烦各位指点一下,呵呵,比较菜的问题啊

解决方案 »

  1.   

    FreeMem(ptr2);     //为什么这里释放的是ptr2,我试验了如果是ptr就会报地址引用错误,
    因为ptr的位置已发生改变,所以不能以ptr来释放
    //如果ptr2释放了,PTR也应该释放啊,为什么没有释放呢?
    这个很多人问过,是对内存释放过程有误解
    内存释放只是将该块内存标记为可用,不等于内存清空,在没有被别人使用前,它的内容是不变的
      

  2.   

    楼主想要的是这样的吧var
      ptr: pinteger;
      I, Ptr2 : Integer;
    begin
      GetMem(ptr, sizeof(integer) * 20);
        //这句等价于C的 ptr = (int*) malloc(sizeof(int) * 20);
      ptr2 := Integer(ptr); //保留原始指针位置
      for i := 0 to 19 do
      begin
        ptr^ := i;
        ShowMessage(IntToStr(ptr^));
        Inc(ptr);
      end;
      ptr := PInteger(Ptr2);
      FreeMem(ptr);     //为什么这里释放的是ptr2,我试验了如果是ptr就会报地址引用错误,
      Dec(ptr,20);       //但是上面的代码如  ptr2 := ptr,如果这样赋值,相当于就引用指针地址了,
      for i:=1 to 20 do   //如果ptr2释放了,PTR也应该释放啊,为什么没有释放呢?
      begin
         ShowMessage(IntToStr(ptr^));
         Inc (ptr)     ;
      end
    end;
      

  3.   


    // FreeMem(ptr2);     //为什么这里释放的是ptr2,我试验了如果是ptr就会报地址引用错误,
    FreeMem(ptr-20);//把指针移到最初始的位置(FreeMem就是以当前指针为基准,释放内存单元长度为N的函数,很明显,你的当前指针不是最初始的位置,而是进行inc(ptr,20)后的位置,故非法访问是正常的)
      

  4.   

    写错了:(dec(ptr,20);
    FreeMem(ptr);
      

  5.   

      ptr := PInteger(Ptr2);
      FreeMem(ptr);     //为什么这里释放的是ptr2,我试验了如果是ptr就会报地址引用错误,
      Dec(ptr,20);       //但是上面的代码如  ptr2 := ptr,如果这样赋值,相当于就引用指针地址了,//此处笔误了 ptr已经指向原来的位置了,后面又Dec
    这个问题很有意思,试验了很多次,作了很多变化,都还是有不太明白的地方
      

  6.   


    var ptr, ptr2 : ^integer;
      i : integer;
    begin
      GetMem(ptr, sizeof(integer) * 20);
        //这句等价于C的 ptr = (int*) malloc(sizeof(int) * 20);
      ptr2 := ptr; //保留原始指针位置
      for i := 0 to 19 do
      begin
        ptr^ := i;
        ShowMessage(IntToStr(ptr^));
        Inc(ptr);
      end;
      //FreeMem(ptr2);     //为什么这里释放的是ptr2,我试验了如果是ptr就会报地址引用错误,
      Dec(ptr,20);       //但是上面的代码如  ptr2 := ptr,如果这样赋值,相当于就引用指针地址了,
      FreeMem(ptr2, sizeof(integer) * 20);     //这一句和上一句作了变化
      for i:=1 to 20 do   //如果ptr2释放了,PTR也应该释放啊,为什么没有释放呢?
      begin
         ShowMessage(IntToStr(ptr^));        //这个地方的结果就奇怪了,前两个地址里面的内容
         Inc(ptr);                           //有错误,但是后面的18个地址中内容却与原来的相同 
      end
    end;
      

  7.   

    呵呵,那代码是原来楼主的, 只大概看了下他的意思,  
    ptr := PInteger(Ptr2); 和 Dec(ptr,20); 后边就可以不要了    
      

  8.   

    如果是注释掉‘Dec(ptr,20); ’,结果如下:
    最开始两个地址空间中内容错误,后面18的地址空间中内容与原来的(循环中赋值)相同
      

  9.   

    为什么要这样写呢,ptr:=pinteger(pstr2).本来就是指针类型,而且是Pstr2引用pstr地址,应该反过来
      

  10.   

    注释掉Dec是因为前面ptr := PInteger(Ptr2); 把ptr指向保留的原来的指针
      

  11.   

    那ptr:=pstr2和pstr:=Pinteger(pstr2)什么区别啊?
      

  12.   


    上边的定义, ptr: pinteger;
      

  13.   

    sanguomi是这样声明变量的:I, Ptr2 : Integer;
    所以才能:pstr:=Pinteger(pstr2);
    其实要实现你的结果,可以这样:var
      ptr, ptr2 : ^integer;
      i : integer;
    begin
      GetMem(ptr, sizeof(integer) * 20);
        //这句等价于C的 ptr = (int*) malloc(sizeof(int) * 20);
      ptr2 := ptr; //保留原始指针位置
      for i := 0 to 19 do
      begin
        ptr^ := i;
        ShowMessage(IntToStr(ptr^));
        Inc(ptr);
      end;
      //FreeMem(ptr2);     //为什么这里释放的是ptr2,我试验了如果是ptr就会报地址引用错误,
      //Dec(ptr,20);       //但是上面的代码如  ptr2 := ptr,如果这样赋值,相当于就引用指针地址了,
      ptr := ptr2;         //这样写的话就可以不用到Dec
      for i:=1 to 20 do   //如果ptr2释放了,PTR也应该释放啊,为什么没有释放呢?
      begin
         ShowMessage(IntToStr(ptr^));
         Inc(ptr);
      end;
      Dec(ptr, 20);        //当然可以作上面一样的变化
      FreeMem(ptr, sizeof(integer) * 20);   //最后来释放申请的内存空间
    end;
    这个FreeMem现在搞得我头晕了
      

  14.   

    Dec(ptr, 20);        //当然可以作上面一样的变化
      FreeMem(ptr, sizeof(integer) * 20);   //最后来释放申请的内存空间上面两行,FreeMem(ptr2, sizeof(integer) * 20);   也可以了,这个地方明白了,呵呵
      

  15.   


    var
      ptr: pinteger;
      I, Ptr2 : Integer;
    begin
      GetMem(ptr, sizeof(integer) * 20);
        //这句等价于C的 ptr = (int*) malloc(sizeof(int) * 20);
      ptr2 := Integer(ptr); //保留原始指针位置
      for i := 0 to 19 do
      begin
        ptr^ := i;
        ShowMessage(IntToStr(ptr^));
        Inc(ptr);
      end;
      ptr := PInteger(Ptr2);
      FreeMem(ptr,sizeof(integer) * 20);     //为什么这里释放的是ptr2,我试验了如果是ptr就会报地址引用错误,
     // Dec(ptr,20);       //但是上面的代码如  ptr2 := ptr,如果这样赋值,相当于就引用指针地址了,
      for i:=1 to 20 do   //如果ptr2释放了,PTR也应该释放啊,为什么没有释放呢?
      begin
         ShowMessage(IntToStr(ptr^));
         Inc (ptr)     ;
      end
    end;这样写为什么会出错呢,我看上去没什么问题啊
      

  16.   

    顶顶,还有想问下,为什么这里Ptr2:=ptr这样子赋值,当ptr的指针值变化的时候,Ptr2没有变化呢,我一直以为有变化的呢,因为是指针引用吗?那什么样的赋值才会引起ptr变化导致ptr2的变化呢?
      

  17.   

    var ptr, ptr2 : ^integer;
    ptr,ptr2本身就是2个变量,类似于
    var x,y:integer;
    Ptr2:=ptr也当于
    x:=y;
    这个与指针没有关系,无论ptr怎样变化,都不会改变Ptr2的值的
      

  18.   

    哦,搞错了,如果ptr2是ptr的指针,那么ptr2地址里面内容的变化,会引起的ptr的变化,还有就是我在18楼,我把三国的那个程序稍微改了,一下,我看上去没有什么错误啊,但是为什么实现不了我的功能呢