kylix AnsiCompareStr 错误?

kylix AnsiCompareStr bug?

以下程序尝试使用 AnsiCompareStr/Text:

program Project5;
{$APPTYPE CONSOLE}
uses StrUtils, SysUtils;

begin
  Writeln('Ord(''-'')=', Ord('-'));
  Writeln('Ord(''_'')=', Ord('_'));
  Writeln('AnsiCompareStr(''-'', ''_'')=', AnsiCompareStr('-', '_'));
  Writeln('AnsiCompareText(''-'', ''_'')=', AnsiCompareText('-', '_'));
  Writeln('WideCompareStr(''-'', ''_'')=', WideCompareStr('-', '_'));
  Writeln('WideCompareText(''-'', ''_'')=', WideCompareText('-', '_'));
  Writeln('CompareStr(''-'', ''_'')=', CompareStr('-', '_'));
  Writeln('CompareText(''-'', ''_'')=', CompareText('-', '_'));
  Readln;
end.

使用 Kylix 编译时,它在 CentOS 5/6 x64 上输出错误结果:

Ord('-')=45
Ord('_')=95
AnsiCompareStr('-', '_')=3   <--- should be negative
AnsiCompareText('-', '_')=3  <--- should be negative
WideCompareStr('-', '_')=3   <--- should be negative
WideCompareText('-', '_')=3  <--- should be negative
CompareStr('-', '_')=-50
CompareText('-', '_')=-50

我想知道为什么 AnsiCompareStr/Text 会给出错误的结果?

PS:CompareStr 根据 http://www.delphibasics.co.uk/RTL.asp?Name=CompareStr . AnsiCompareStr is considered to be the modern, Locale safe form of CompareStr according to http://www.delphibasics.co.uk/RTL.asp?Name=AnsiCompareStr 被认为已过时。

PS: 语言环境是 en_US.iso885915 and/or en_US.UTF8

PS:Kylix 3(如 Delphi 7 和 CrossKylix)

function AnsiCompareStr(const S1, S2: string): Integer;
begin
{$IFDEF MSWINDOWS}
  Result := CompareString(LOCALE_USER_DEFAULT, 0, PChar(S1), Length(S1),
    PChar(S2), Length(S2)) - 2;
{$ENDIF}
{$IFDEF LINUX}
  // glibc 2.1.2 / 2.1.3 implementations of strcoll() and strxfrm()
  // have severe capacity limits.  Comparing two 100k strings may
  // exhaust the stack and kill the process.
  // Fixed in glibc 2.1.91 and later.
  Result := strcoll(PChar(S1), PChar(S2));
{$ENDIF}
end;

function AnsiCompareText(const S1, S2: string): Integer;
begin
{$IFDEF MSWINDOWS}
  Result := CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, PChar(S1),
    Length(S1), PChar(S2), Length(S2)) - 2;
{$ENDIF}
{$IFDEF LINUX}
  Result := WideCompareText(S1, S2);
{$ENDIF}
end;

AnsiCompareStr/Text 给出了正确的结果。它们反映了流行语言环境定义的顺序。例如 AnsiCompareStr 是通过从 glibc 标准库简单调用 strcoll 来实现的。

问题出在你的意料之中。我不确定您为什么期望得到您所做的结果,但是期望 glibc 正确实现排序规则是很合理的。 strcoll 隐含的顺序是当前语言环境的整理顺序,无论它是什么。你没有在问题中说明这一点。

也许线索是您使用了短语 locale safe。好吧,CompareXXX 独立于语言环境,AnsiCompareXXX 取决于语言环境。如果您正在寻找语言环境不变的顺序,那么 AnsiCompareXXX 是错误的选择。