1

我使用以下方法来移动和操作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变了。。。

为什么在大多数语句之后p正确引用一个字符,并在一些调用后突然停止工作?sInsert()Insert()

(我在输入问题时发现了问题的答案。现在答案似乎很明显,但在我为这个问题苦苦挣扎时却并非如此。也许发布问题和答案会对其他人有所帮助......)

4

1 回答 1

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;
于 2013-02-22T01:31:57.327 回答