【问题标题】:Delphi AnsiString Manipulation - PAnsiChar becomes corrupt?Delphi AnsiString 操作 - PAnsiChar 损坏?
【发布时间】:2013-02-07 13:13:45
【问题描述】:

我使用以下方法来移动和操作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>'。这符合预期。

我的真实字符串有几千个字符长。这种在字符串中移动并添加新字段的方法工作了几十次,然后突然停止工作。在调用Insert() 之后,p 不再在字符串前面显示插入的值。 p 好像不知道s 变了……

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

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

【问题讨论】:

  • 仅供参考:在您的问题和答案中,您永远不会在循环中使用 offset 之前对其进行初始化。因此,您从随机内存内容开始,并在每次循环中以 idx 的值递增它。
  • 如果存在的话,您真正可以在这里使用的是“AnsiPosEx”,该函数将 AnsiPos 的 MBCS 感知与 PosEx 的可配置起始索引相结合。那么您根本不需要p,这样每次您将p 作为需要AnsiString 的参数传递并且编译器会自动转换为你。如果您的搜索词确实是一个字符,请考虑改用 AnsiStrScan。
  • 好的cmets。多谢你们。我的实际代码初始化offset - 我只是在这里忽略了它。我也会看看 AnsiPosEx 和 AnsiStrScan。谢谢!

标签: delphi pointers delphi-xe2 ansistring


【解决方案1】:

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

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

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;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-03-07
    • 2012-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-09
    • 1970-01-01
    相关资源
    最近更新 更多