本帖最后由 bzworinima 于 2011-06-22 11:20:32 编辑

解决方案 »

  1.   

    Move和CopyMemory是一样的,只是参数调用有点区别而已。CopyMemory只是对Move做了简单包装,自己Ctrl+左键单击copyMemory就知道了
      

  2.   

    后记:   使用Move 可以减少系统频繁开辟新内存区, 但是,增加了模块间的耦合度, 容易造成指针丢失 (忘记释放);   使用CopyMemory 可以减少模块间的耦合度, 每个模块的资源都是在内部创建,和释放, 是个良好的编程习惯, 但是增加系统频繁开辟新内存区。楼上,你没看我做了测试吗? 你试试就知道了,虽然我非常清楚 VCL 的封装
      

  3.   

    编写错误
     这里应该是
    //Dispose(ABuffer); //使用CopyMemory 复制数据,释放数据源指针 $29580D0
      Dispose(P); //使用CopyMemory 复制数据,释放数据源指针 $29580D0
      

  4.   

    Move的效果相当于“剪切”-“粘贴”
    CopyMemory的效果相当于“复制”-‘粘贴’
      

  5.   

    你这个贴很容易误导新人。Move和CopyMemory本来是同一个东西,参数稍变结果你就调错了还不知道。看下面你的DEMO:
      new(P);  Move(ABuffer,P, Sizeof(ABuffer)); //可以将数据复制到P, ABuffer 和 P 指向同一个内存区 , ABuffer = $29580D0 ,ip= '192.168.1.132',P = $29580D0这个只是把指针ABuffer的四个字节拷贝到P,而不是拷贝指针指向的内存块,所以持行这个的结果是ABuffer和P都指向一块内存,效果和P:=ABuffer一样。你应该这样调:Move(ABuffer^,P^, Sizeof(TArrayByte));
    而用CopyMemory是这样:
    CopyMemory(P,ABuffer, Sizeof(TArrayByte));这两个是等效的。注意Move和CopyMemory的参数,两个的参数是不一样的,Move的参数传的是数据块的地址,而CopyMemory传的是指针
      

  6.   

    我觉得你没有理解move的作用
    procedure CopyMemory(Destination: Pointer; Source: Pointer; Length: DWORD);
    begin
      Move(Source^, Destination^, Length);
    end;
    move和CopyMemory的作用是一样的,只不过move的参数被设成const,var,就相当于c++的引用,调用时实际上还是传地址,如果你要用move复制一块内存,就move(pointer1^,pointer2^,length)
    而且move也是复制,很多复制的都用move这个词,比如memmove,RtlMoveMemory,mov指令等
      

  7.   

    就是很容易搞错,我才上这个帖子的正确的应用是这样的:
    Move(ABuffer,P, Sizeof(ABuffer));   //指针传递            Move(ABuffer^,P^, Sizeof(TArrayByte));   //复制内存块CopyMemory(@P, @ABuffer, SizeOf(ABuffer)); //指针传递CopyMemory(P,ABuffer, Sizeof(TArrayByte));//复制内存块
      

  8.   

    move里第一句是,  S := PChar(@Source); 这里会对Source进行一个“取地址操作”,所以如果要复制内存块,move的参数不能是指针而必须是指针指向的“内容”而CopyMemory就是Move(Source^, Destination^, Length); 无非是帮你做个“指针”->“内容”的变化,应该是为了符合一般c++程序员操作指针的习惯,所以CopyMemory接收的是指针
      

  9.   

    lz 的贴子纯粹胡说八道,Move 根本就没用对,属于拉不出来屎怪地球没吸引力的类型
      

  10.   

    我对数据的理解是这样的。
    1234+array of byte 四字节的地址,之后跟着一堆 Byte
    PArrayByte 其实就是 地址 + TArrayByte
    @TArrayByte 表示的就是 这个地址。
    Move中的参数 const ABuf 相当于第二行中的 array of byte
    CopyMemory中的参数 Pointer 相当于第二行中的 1234
    所以 Move PArrayByte 的时候,应该是 p^ 加个小尾巴。
    CopyMemory PArrayByte 不用特殊处理。
    CopyMemory TArrayByte ,应该加个 @。
      

  11.   

    讨论技术问题,对错很正常。本帖展示出csdn论坛delphi版风气不好。
      

  12.   

    truexf
     说的很对, 在讨论中成长, 共勉, 我提出这个问题,不代表我不懂, 是希望不太熟悉的人看了后,发现自己也在犯同样的错误, 有亲切感, 有错改之, 如果只贴
    正确的应用是这样的:
    Move(ABuffer,P, Sizeof(ABuffer)); //指针传递   
    Move(ABuffer^,P^, Sizeof(TArrayByte)); //复制内存块
    CopyMemory(@P, @ABuffer, SizeOf(ABuffer)); //指针传递
    CopyMemory(P,ABuffer, Sizeof(TArrayByte));//复制内存块
    理解有这么深刻吗? delphi论坛发展已经很艰难了,希望大家以后能有个好风气,以良好的心态,不要浮躁, 不要乱扔砖头
      

  13.   

    学习的前期过程是模仿的过程, 初学者开始用CopyMemory时, 发现前辈的程序里,有时候带@ ,有时候不带,  用Move时, 有时候带^, 有时候不带,Sizeof() 里面 ABuffer ,TArrayByte 都可以,用length()也可以, 系统编译不出错, 但是,运行结果却不同,本贴,以抛砖引玉的形式,讲了用法的区别。
    谢谢大家关注!
      

  14.   

    唉, 03年在CSDN 求学的时候 那些带星的前辈, 周爱民, aii ,孟子E章等人的大师风范,CSDN里很难看到了,更多的是浮躁,傲气
      

  15.   

    教你一个乖,把说别人的话用在自己身上,多反省反省自己。
    一个人明明是自己错了用不明白,胡说八道了一堆,还不许别人说。你说是这样的人浮躁、傲气,还是说他的人浮躁、傲气?
    03年的时候你用 delphi 是一个菜,现在8年过去了,你还是菜得连最基本的语法都搞不清楚。连参数声明代表什么语义都弄不清楚,也好意思说自己在“讨论技术”?不用说,就你这态度,我敢说再过8年你还是一样菜。CSDN 水平差是个不争的事实,原因就是你这种层次的人太多。不懂还到处乱讲也还罢了,别人指出来还说别人人品差。
    提高论坛水平一个最有效的办法就是:一旦有乱讲的就大家一起喷,喷到再没人敢自己不懂还瞎指导、不但满嘴跑火车还唧唧歪歪,自然层次就上去了。
      

  16.   


    发帖交流经验没错,出现错误也很正常,谁都有粗心大意的时候,“大师”也不例外!
    我以前也看过很多和LZ类似的错误,人家在别人指出或者自己发现后,总是说“对不起,我自己搞错了,谢谢XXX的提醒(或者应该怎样怎样的)”,而不像LZ非但不去检查自己是否错了?错在哪里?而是百般狡辩什么:“虽然我非常清楚 VCL 的封装”、“在讨论中成长,共勉”、“就是很容易搞错,我才上这个帖子的”、“我搞这个帖子是给不清楚的人看的”看得等等。况且该帖不是什么深奥的技术问题,而是很常见的类型混淆错误,有必要“在讨论中成长,共勉”吗?
    自己不虚心,反倒倒打一耙,说别人“浮躁,傲气”、无“大师风范”,真有点是非颠倒!
      

  17.   

    当源和目标对应的内存地址范围有重叠时,Move保证结果是正确的,Copy不能保证。
      

  18.   

    还以为有高手提问题,原来是不知道函数怎么用,若想了解delphi内存管理,甚至想知道原理,建议至少看过一遍Getmem.inc文件
      

  19.   

    delphi中move函数的用法 
    Move(pSource,pDest,len); //错误
    Move(pSource^,pDest^,len); //正确
      

  20.   

    源代码是这样:procedure       Move( const Source; var Dest; count : Integer );
    {$IFDEF PUREPASCAL}
    var
      S, D: PChar;
      I: Integer;
    begin
      S := PChar(@Source);
      D := PChar(@Dest);
      if S = D then Exit;
      if Cardinal(D) > Cardinal(S) then
        for I := count-1 downto 0 do
          D[I] := S[I]
      else
        for I := 0 to count-1 do
          D[I] := S[I];
    end;
    {$ELSE}
    asm
    {     ->EAX     Pointer to source       }
    {       EDX     Pointer to destination  }
    {       ECX     Count                   }        PUSH    ESI
            PUSH    EDI        MOV     ESI,EAX
            MOV     EDI,EDX        MOV     EAX,ECX        CMP     EDI,ESI
            JA      @@down
            JE      @@exit        SAR     ECX,2           { copy count DIV 4 dwords       }
            JS      @@exit        REP     MOVSD        MOV     ECX,EAX
            AND     ECX,03H
            REP     MOVSB           { copy count MOD 4 bytes        }
            JMP     @@exit@@down:
            LEA     ESI,[ESI+ECX-4] { point ESI to last dword of source     }
            LEA     EDI,[EDI+ECX-4] { point EDI to last dword of dest       }        SAR     ECX,2           { copy count DIV 4 dwords       }
            JS      @@exit
            STD
            REP     MOVSD        MOV     ECX,EAX
            AND     ECX,03H         { copy count MOD 4 bytes        }
            ADD     ESI,4-1         { point to last byte of rest    }
            ADD     EDI,4-1
            REP     MOVSB
            CLD
    @@exit:
            POP     EDI
            POP     ESI
    end;
    {$ENDIF}
    =======================================procedure CopyMemory(Destination: Pointer; Source: Pointer; Length: DWORD);
    begin
      Move(Source^, Destination^, Length);
    end;
      

  21.   

    41楼贴的是哪个版本的代码?D7以上版本Move过程中的汇编码与你这个是不一样的。
      

  22.   

    大家仔细看他那个ID :bzworinima ="版猪我日你妈" 。。
      

  23.   

    D7的汇编码是这样的:
    asm
    {     ->EAX     Pointer to source       }
    {       EDX     Pointer to destination  }
    {       ECX     Count                   }        PUSH    ESI
            PUSH    EDI        MOV     ESI,EAX
            MOV     EDI,EDX        MOV     EAX,ECX        CMP     EDI,ESI
            JA      @@down
            JE      @@exit        SAR     ECX,2           { copy count DIV 4 dwords       }
            JS      @@exit        REP     MOVSD        MOV     ECX,EAX
            AND     ECX,03H
            REP     MOVSB           { copy count MOD 4 bytes        }
            JMP     @@exit@@down:
            LEA     ESI,[ESI+ECX-4] { point ESI to last dword of source     }
            LEA     EDI,[EDI+ECX-4] { point EDI to last dword of dest       }        SAR     ECX,2           { copy count DIV 4 dwords       }
            JS      @@exit
            STD
            REP     MOVSD        MOV     ECX,EAX
            AND     ECX,03H         { copy count MOD 4 bytes        }
            ADD     ESI,4-1         { point to last byte of rest    }
            ADD     EDI,4-1
            REP     MOVSB
            CLD
    @@exit:
            POP     EDI
            POP     ESI
    end;
      

  24.   

    我的D7汇编码是这个样子的:asm
      cmp     eax, edx
      je      @@Exit {Source = Dest}
      cmp     ecx, 32
      ja      @@LargeMove {Count > 32 or Count < 0}
      sub     ecx, 8
      jg      @@SmallMove
    @@TinyMove: {0..8 Byte Move}
      jmp     dword ptr [@@JumpTable+32+ecx*4]
    @@SmallMove: {9..32 Byte Move}
      fild    qword ptr [eax+ecx] {Load Last 8}
      fild    qword ptr [eax] {Load First 8}
      cmp     ecx, 8
      jle     @@Small16
      fild    qword ptr [eax+8] {Load Second 8}
      cmp     ecx, 16
      jle     @@Small24
      fild    qword ptr [eax+16] {Load Third 8}
      fistp   qword ptr [edx+16] {Save Third 8}
    @@Small24:
      fistp   qword ptr [edx+8] {Save Second 8}
    @@Small16:
      fistp   qword ptr [edx] {Save First 8}
      fistp   qword ptr [edx+ecx] {Save Last 8}
    @@exit:
      ret
      nop {4-Byte Align JumpTable}
      nop
    @@JumpTable: {4-Byte Aligned}
      dd      @@Exit, @@M01, @@M02, @@M03, @@M04, @@M05, @@M06, @@M07, @@M08
    @@LargeForwardMove: {4-Byte Aligned}
      push    edx
      fild    qword ptr [eax] {First 8}
      lea     eax, [eax+ecx-8]
      lea     ecx, [ecx+edx-8]
      fild    qword ptr [eax] {Last 8}
      push    ecx
      neg     ecx
      and     edx, -8 {8-Byte Align Writes}
      lea     ecx, [ecx+edx+8]
      pop     edx
    @FwdLoop:
      fild    qword ptr [eax+ecx]
      fistp   qword ptr [edx+ecx]
      add     ecx, 8
      jl      @FwdLoop
      fistp   qword ptr [edx] {Last 8}
      pop     edx
      fistp   qword ptr [edx] {First 8}
      ret
    @@LargeMove:
      jng     @@LargeDone {Count < 0}
      cmp     eax, edx
      ja      @@LargeForwardMove
      sub     edx, ecx
      cmp     eax, edx
      lea     edx, [edx+ecx]
      jna     @@LargeForwardMove
      sub     ecx, 8 {Backward Move}
      push    ecx
      fild    qword ptr [eax+ecx] {Last 8}
      fild    qword ptr [eax] {First 8}
      add     ecx, edx
      and     ecx, -8 {8-Byte Align Writes}
      sub     ecx, edx
    @BwdLoop:
      fild    qword ptr [eax+ecx]
      fistp   qword ptr [edx+ecx]
      sub     ecx, 8
      jg      @BwdLoop
      pop     ecx
      fistp   qword ptr [edx] {First 8}
      fistp   qword ptr [edx+ecx] {Last 8}
    @@LargeDone:
      ret
    @@M01:
      movzx   ecx, [eax]
      mov     [edx], cl
      ret
    @@M02:
      movzx   ecx, word ptr [eax]
      mov     [edx], cx
      ret
    @@M03:
      mov     cx, [eax]
      mov     al, [eax+2]
      mov     [edx], cx
      mov     [edx+2], al
      ret
    @@M04:
      mov     ecx, [eax]
      mov     [edx], ecx
      ret
    @@M05:
      mov     ecx, [eax]
      mov     al, [eax+4]
      mov     [edx], ecx
      mov     [edx+4], al
      ret
    @@M06:
      mov     ecx, [eax]
      mov     ax, [eax+4]
      mov     [edx], ecx
      mov     [edx+4], ax
      ret
    @@M07:
      mov     ecx, [eax]
      mov     eax, [eax+3]
      mov     [edx], ecx
      mov     [edx+3], eax
      ret
    @@M08:
      fild    qword ptr [eax]
      fistp   qword ptr [edx]
    end;
      

  25.   

    个人认为用std是考虑内存重叠的问题,很久没摸过delphi和Object Pascal了,现在理论上的东西都很生疏了,岁月不饶人啊……
    另外说一句不是很好听的,我推荐这个帖子是因为大家的回复而不是楼主的言论,我希望楼主能读下大家的回复,自己去system头文件里面看看汇编码,然后再来讨论下这个问题。
    procedure CopyMemory(Destination: Pointer; Source: Pointer; Length: DWORD);
    begin
      Move(Source^, Destination^, Length);
    end;
    另外说一句,这个procedure CopyMemory在widnows头文件里面,烦请您自己ctrl+鼠标左键点进去自己看看
    copymemory只是对move函数的一个封装而已
    正如楼上所说,一个是指针一个是地址而已,换个方式本质还是一样的
      

  26.   

    阿发伯您的汇编码好像是Delphi2007版本的……
    我记得2007里面才有@@LargeForwardMove这种命名
      

  27.   

    对了,我好想想起来了,那个汇编码似乎是FastCode的改版
    Delphi在2007以后很多地方都参考了FastCode的设计,应该有这方面的原因
      

  28.   

    我也想起来了,我安装D7后又装了一个《Borland Delphi 7 FastMM RTL 补丁》的,可能有些文件被替换了。
      

  29.   

    丫瞎扯呢,Move 和 CopyMemory 的作用完全相同。
    前面有个说“当源和目标对应的内存地址范围有重叠时,Move保证结果是正确的,Copy不能保证。”的,也跟 delphi 毛关系都没有。c89、c99 标准里倒是有(cpp 的标准里应该也有),当内存地址重叠时,标准库里 memcpy 的行为是 undefined,八成是自己在哪看到过但没记清楚是哪个语言的。这里带星星的菜鸟也不止一个两个。别说就1颗的,还有5颗星还照样菜的
      

  30.   


    我来试着解释一下,有错误请大侠们指正:Move过程的原型为:
    procedure Move(const Source; var Dest; count : Integer);
    其中的Source和Dest形参是典型的pascal无符号类型,可接收任意类型的实参。如果用C函数改写,可以是:
    void Move(const void *Source, void *Dest, int Count);
    但是在调用语法上,二者是不相同的。pascal过程传递的是任意类型实参本身,而C函数传递的是指向任意实参的指针。事实上,通过编译器编译后,二者的实参传递方式是完全相同的,即都是以地址方式传递的,只不过pascal过程是靠编译器的“帮忙”来完成的,这和C++函数的引用参数有些类似(只是类似,因C++引用不能使用在无符号类型上)。CopyMemory是一个Windows API函数,其原型是C形式的:
    VOID CopyMemory(PVOID Destination, CONST VOID *Source, DWORD Length);
    只不过在delphi中这个Windows API函数被替换成了下面这个样子:
    procedure CopyMemory(Destination: Pointer; Source: Pointer; Length: DWORD);
    begin
      Move(Source^, Destination^, Length);
    end;
      

  31.   

    哦,忘说了,“Move的效果相当于“剪切”-“粘贴”,CopyMemory的效果相当于“复制”-‘粘贴’”是错误的。
      

  32.   

    关于这个 我倒记得 ,是 C99 memcpy 和 memmove ...
      

  33.   

    vc里面的CopyMemory就是memcpy
    kernel32也没有导出CopyMemory,而是导出RtlMoveMemory,还是个转向导出,实际的代码在ntdll.dll中
      

  34.   


    Copy & Paste ...
      

  35.   

    我是来顶老毛的!仅此而已!其他不做评论!也评论不了,俺是小辈来的,07年才开始Delphi,03年,我还不晓得Delphi是什么了,^_^!