PChar的修改问题:     在使用StrMove和Move等过程中经常会产生问题。例如以下代码
    var
      Ps1,Ps2:PChar;
    begin
      Ps1 := 'ABCDEF';
      Ps2 := 'GHIJKL';
      Move(Ps1[0], Ps2[0], 3);  //Error
      //Ps1[0] := 'Z'
    end;    以上代码初看没有什么问题,然而实际运行发现在Move句出错了!而且对于//Ps1[0] := 'Z' 这句也会出错。    考察String的使用
    var
      Ps1,Ps2:String;
    begin
      Ps1 := 'ABCDEF';
      Ps2 := 'GHIJKL';
      Move(Ps1[1], Ps2[1], 3);  
      //Ps1[1] := 'Z'
    end;
    这里却表现十分正常。    那么原因在哪里呢?    分析: 在第一段代码中,Ps1 := 'ABCDEF'此句的赋植操作是个单纯的指针操作。即将存放'ABCDEF'的地址赋值给Ps1,但是有一点要明确,'ABCDEF'的地址空间是在进程的地址空间,通俗的说就是和执行代码在同一空间。而不是在进程分配的堆的地址空间。由于进程的地址空间是受系统保护的,可读不可写。因此,对这个地址进行写就会出错。因此,考虑改成以下代码,运行正常:
         var
           Ps1,Ps2:PChar;
         begin
           Ps1 := 'ABCDEF';
           GetMem(Ps2,6)
           Move(Ps1[0], Ps2[0], 3);  
         end;
原因很简单,因为GetMem为Ps2在堆中开辟了空间
而第二段代码中,Ps1 := 'ABCDEF'由于Ps1是String类型,它的赋值操作其实是先开辟一段空间,然后把串复制到该地址空间。因此,在后面的Move操作就完全没问题。 
以上分析提到了进程代码运行修改问题,可参看ReadProcessMemory WriteProcessMemory以及VirtualProtect等API函数,特别是VirtualProtect 2002.6.28 周文杰