Delphi AnsiString操作 - PAnsiChar变得腐败?

时间:2013-02-22 01:28:37

标签: delphi pointers delphi-xe2 ansistring

我使用以下方法来移动并操纵AnsiString。它大部分时间都有效,但有时指向字符串的指针退出运行。给出以下代码:

var
  s: AnsiString;
  p: PAnsiChar;
  offset, idx, cnt: Integer;
begin
  s := 'some>very>long>string>with>field>delimiters>';
  p := @s[1];
  offset := 1;

  // find the 5th field
  cnt := 5;
  repeat
    idx := AnsiString.AnsiPos('>', p);
    Inc(p, idx);
    Inc(offset, idx);
    Dec(cnt);
  until cnt = 0;

  // insert a new field after the 5th field
  Insert(AnsiString('something new>'), s, offset);

  // skip other fields
  // insert other values
  // repeat
end;

调试时,在repeat..until循环结束后,您可以查看检查器并查看p = 'field>delimiters>'。在检查员中Insert()语句s = 'some>very>long>string>with>something new>field>delimiters>'p = 'something new>field>delimiters>'之后。这是预期的。

我的真正字符串长达数千个字符。这种在字符串中移动并添加新字段的方法可以工作几十次,然后突然停止工作。调用p后,Insert()不再显示字符串前面的插入值。 p似乎并不知道s已经改变了......

为什么ps语句后Insert()正确引用了某个字符,并在拨打Insert()之后突然停止工作?

(我在打字时发现了我的问题的答案。现在答案显而易见,但在我遇到问题的时候并不是这样。也许发布问题和答案会帮助别人...... )

1 个答案:

答案 0 :(得分:7)

当您调用Insert()时,如果没有足够的额外连续内存来扩展当前内存位置的缓冲区,内存管理器会将AnsiString移动到内存中的新位置。这使p指向旧的内存位置,该位置不包含修改后的字符串,并可能导致访问冲突。

在每个p语句后添加一行代码以重新初始化Insert()可以解决问题。

var
  s: AnsiString;
  p: PAnsiChar;
  offset, idx, cnt: Integer;
begin
  s := 'some>very>long>string>with>field>delimiters>';
  p := @s[1];
  offset := 1;

  // find the 5th field
  cnt := 5;
  repeat
    idx := AnsiString.AnsiPos('>', p);
    Inc(p, idx);
    Inc(offset, idx);
    Dec(cnt);
  until cnt = 0;

  // insert a new field after the 5th field
  Insert(AnsiString('something new>'), s, offset);
  p := @s[offset];                                 // <- this fixes the issue

  // skip other fields
  // insert other values
  // repeat
end;