-2

在旧版本的 Delphi 中,比如 D7,你可以像ord(s[i])where s 是一个字符串那样做,但是用 AnsiString 尝试这个会导致异常(访问冲突)。

PS我很长一段时间都在使用delphi 7。

以下是重现错误的步骤: 创建一个新项目并通过表单上的备忘录(让它成为 memo1),然后将以下代码添加到表单创建事件处理程序:

procedure TForm1.FormCreate(Sender: TObject);
var u: ansistring;
begin
    u := 'stringtest';
    memo1.Lines.Add(inttostr(ord(u[2])));
end;

对我来说,这段代码产生了一个 AV。

4

1 回答 1

3

它确实与 ansistring 一起使用,但您无法阅读它的末尾,并且您必须确保该字符串已初始化。

function CharCode(const S: ansistring; pos: integer): byte;
begin
  if pos <= 0 then result:= 0
  //else if s='' then Result:= 0 //unassigned string;
  else if Length(s) < Pos then Result:= 0  //cannot read past the end.
  else Result:= Ord(s[pos]);
end;

请注意,if s=''这与询问相同if pointer(s) = nil。一个空字符串实际上是一个 nil 指针。
这可能就是您遇到访问冲突的原因。

如果你想强制 ansistring 达到一定的长度,你可以使用SetLength(MyAnsistring, NewLength);

(ansi) 字符串的长度是可变的。这意味着它会根据需要增长和缩小。如果您阅读超过字符串的末尾,您可能会遇到访问冲突。
请注意,您不必获得AV,RTL 在其分配中留下了一些松弛;它通常分配比请求稍大的缓冲区,这是由于性能和架构原因。

如果读取到字符串的末尾,您可能无法获得 AV 的另一个原因是您的程序可能同时拥有字符串缓冲区以及恰好在它旁边的任何内容。

出于这个原因,在调试模式下启用范围检查是个好主意,{$R+}它会添加额外的检查以防止读取超出结构的末尾。

短字符串和 (ansi) 字符串的区别
短字符串具有固定长度,并且存在于堆栈中。
长字符串(ansi 或宽)是指向在堆上分配的记录的指针;它看起来像这样:

type
  TStringRecord = record
    CodePage: word;     
    ElementSize: word; //(1, 2 or 4)    
    ReferenceCount: integer;    
    Length: Integer;    
    StringData: array[1..length(s)] of char;
    NullChar: char;
  end;

编译器会对您隐藏所有这些细节。
请参阅:http ://docwiki.embarcadero.com/RADStudio/Seattle/en/Internal_Data_Formats

于 2016-04-13T21:22:51.483 回答