CJC Delphi 技巧馆's Archiver

cjc Posted at 2018-9-20 10:54

(string) 直接用指针操作字符串的运行错误 及 潜在危险 (2005.6.16)

cjc 2005.6.16

直接用指针操作字符串的运行错误 及 潜在危险, 会导致引用的字符串同时被修改.

以下代码会产生执行错误
var
  p: Pchar;
  s,s1,s2: string;
begin
  s := 'ABDDEFGHIJKLNOPQ';
  P := PChar(s);
  P^ := '-';
end;
原因: s指定一串常量,估计是编译器没真正给s分配内存空间(堆空间), 所以直接写入时产生运行错。


以下代码同样会产生执行错误
const kkk: string = 'this is a test';
procedure test;
var
  p: Pchar;
  s,s1,s2: string;
begin
  s := kkk;
  P := PChar(s);
  P^ := '-';
end;
原因: 理由同上, kkk也是一个常量串,它付给s时只进行的计数引用,并不真正生成新字符串。


作为参数, 同样报错:
procedure test(sss: string);
var
  p: Pchar;
  s,s1,s2: string;
begin
  s := sss;
  P := PChar(s);
  P^ := '-';
end;

test('abcdefg');

理由还是一样。

解决的办法就是不直接使用指针,使用 S[1] := '-'; 则不会报错。

*** 上述情况,P^ 可以读,但不能写 ***
**** 所以, 在子程序内使用指针操作要十分注意,因为你无法确定调用此子程序时传 ****
**** 递的参数是否常量字符串。 如果一定要使用指针,必须确保你所处理的字符串的****
**** 引用是唯一的。使用 procedure UniqueString(var S: string); 函数能保证引 ****
**** 用唯一 。 ***



指针直接操作的潜在危险:

procedure test(sss: string);
var
  p: Pchar;
  s,s1,s2: string;
begin
  s := sss;
  UniqueString(s);
   ...
  s1 := s;
  s2 := s;
  P := PChar(s2);
  P^ := '-';
end;

上面例子的结果是:  s,s1,s2三个字符串的第一个字串都变成了'-', 而不仅仅是s2变了。
原因是 s,s1,s2 实际上都只引用了同一个字符串, 指向同一个内存区域。

如果是使用s2[1] := '1' 则只会修改s2本身,因为编译器能识别出s2要进行修改,自动
进行了UniqueString(s2);  但直接指针操作,编译器无法识别。
使用delphi本身的字符串操作函数都会自动按需要调用UniqueString, 包括: copy, move, fillchar, stringReplace, SetString, SetLength 等.

Page: [1]
CJC好玩背单词最新版本 - 是目前最好的背单词软件,游戏好玩,功能强大,词库众多,还有真人语音,免费下载,免费试用 !

Powered by Discuz! Archiver 6.1.0  © 2001-2007 Comsenz Inc.