Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2016-03

AnsiCompareStr question (again...)

9 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Marcou Gilles

Hi,

in an application, I use a TStringList.Sort to sort a list of these two words "(C-C)" and "(C=C)". When I use the same unit in another project, the Sort function sort those two strings in revert order (on the same computer, same system).

I checked the AnsiCompareStr value between these two string and found that the same unit compiled into one application give the value 16 and compiled into the other application, it return the value -28.

I am really puzzled. Does it has something to do with the WideStringManager? I don't understand how to fix this to guarantee the same behavior of this function at any time on any system.

Thanks in advance,
Gilles Marcou

Bart
to Marcou Gilles
Marcou Gilles wrote
I checked the AnsiCompareStr value between these two string and found that the same unit compiled into one application give the value 16 and compiled into the other application, it return the value -28.
{$apptype console}
{$ifdef fpc}
{$mode objfpc}
{$h+}
//{$codepage utf8}
{$endif}
uses SysUtils;
var
  S1,S2: AnsiString;
begin
  S1 := 'C-C';
  S2 := 'C=C';
  writeln('AnsiCompareStr(''C-C'',''C=C'') = ',ansicomparestr(S1,S2));
end.

C:\Users\Bart\LazarusProjecten\ConsoleProjecten>fpc test.pas Free Pascal Compiler version 3.0.0 [2015/11/16] for i386 Copyright (c) 1993-2015 by Florian Klaempfl and others Target OS: Win32 for i386
Compiling test.pas
Linking test.exe
16 lines compiled, 2.5 sec, 64048 bytes code, 4052 bytes data

C:\Users\Bart\LazarusProjecten\ConsoleProjecten>test AnsiCompareStr('C-C','C=C') = 1

(Same result with fpc 2.6.4)

Bart

Marcou Gilles
to Bart

Thanks Bart,

this is strange. Using you example I got the value -16. I am using fpc 2.6.4 on a Linux 64 bits machine. I do not get why I got a different value than you. And in my case, the strange behavior is that AnsiCompareStr in the same unit but in two different application gave two different results. I wonder if somebody else got observed this?

I also noticed that using CompareStr, I got the value -16 and the funtion give the same result on both application. The code where I observe this are rather large, so it is difficult to share. But if I manage to recreate this situation in a more simple context, I'll post a bug report.

Thanks again for your help,
Gilles Marcou

Bart wrote 39 lines
On 3/5/16, Marcou Gilles wrote: > I checked the AnsiCompareStr value between these two string and found > that the same unit compiled into one application give the value 16 and > compiled into the other application, it return the value -28. {$apptype console} {$ifdef fpc} {$mode objfpc} {$h+} //{$codepage utf8} {$endif} uses SysUtils; var S1,S2: AnsiString; begin S1 := 'C-C'; S2 := 'C=C'; writeln('AnsiCompareStr(''C-C'',''C=C'') = ',ansicomparestr(S1,S2)); end. C:\Users\Bart\LazarusProjecten\ConsoleProjecten>fpc test.pas Free Pascal Compiler version 3.0.0 [2015/11/16] for i386 Copyright (c) 1993-2015 by Florian Klaempfl and others Target OS: Win32 for i386 Compiling test.pas Linking test.exe 16 lines compiled, 2.5 sec, 64048 bytes code, 4052 bytes data C:\Users\Bart\LazarusProjecten\ConsoleProjecten>test AnsiCompareStr('C-C','C=C') = 1 (Same result with fpc 2.6.4) Bart
Jonas Maebe
to Marcou Gilles
Marcou Gilles wrote 5 lines
this is strange. Using you example I got the value -16. I am using fpc 2.6.4 on a Linux 64 bits machine. I do not get why I got a different value than you. And in my case, the strange behavior is that AnsiCompareStr in the same unit but in two different application gave two different results. I wonder if somebody else got observed this?

One probably includes cwstring, while the other one doesn't. AnsiCompareStr can be intercepted/replaced by widestring manages such as cwstring.

The default implementation of AnsiCompareStr just compares based on ASCII values. cwstring also takes the locale into account.

Jonas

Bart
to Jonas Maebe
Jonas Maebe wrote
One probably includes cwstring, while the other one doesn't. AnsiCompareStr can be intercepted/replaced by widestring manages such as cwstring.

Sample from above on Linux 32-bit:
ConsoleProjecten]$ ./test
AnsiCompareStr('C-C','C=C') = -16

Same program, but now added cwstring to uses clause:

ConsoleProjecten]$ ./test
AnsiCompareStr('C-C','C=C') = 28

CompareStr returns -16 in both win32 and linux-32 b.t.w.

Bart

Tomas Hajny
to Bart
Bart wrote 14 lines
On 3/5/16, Jonas Maebe wrote: > One probably includes cwstring, while the other one doesn't. > AnsiCompareStr can be intercepted/replaced by widestring manages such as > cwstring. Sample from above on Linux 32-bit: ConsoleProjecten]$ ./test AnsiCompareStr('C-C','C=C') = -16 Same program, but now added cwstring to uses clause: ConsoleProjecten]$ ./test AnsiCompareStr('C-C','C=C') = 28

Note that there may be a difference not only between the fallback implementation and a real WideString / UnicodeString manager, but also between WideString / UnicodeString managers used on different platforms - as an example, we cannot guarantee that the results are exactly the same on MS Windows (using its default Unicode string handling routines), Linux with cwstring (depending on the iconv library), AIX with the IBM implementation of iconv and OS/2 with yet another IBM implementation of Unicode string handling routines.

If you want to ensure that the behaviour is exactly the same even for various symbols, you should probably use fpwidestring - this results in bigger binaries, but the same code is used across all supported platforms.

Tomas

Marcou Gilles
to Jonas Maebe: One probably includes cwstring, while the other one doesn't. AnsiCompareStr can be…

Thanks for your answer Jonas.

One probably includes cwstring, while the other one doesn't. AnsiCompareStr can be intercepted/replaced by widestring manages such as cwstring.

Is it what is meant into the manual by: "A widestring manager must be installed in order for this function to work correctly with various character sets"? Frankly I don't understand what is a widestring manager in the first place and how do I know if one is installed in the second. Somebody can explain?

Another question is: do the cwstring unit call a system library (.dll/.o/.so)? In that case, maybe my problem was due to a memory management problem. Is it possible that a memory leak problem could interfere with a system library?

Thanks for your help,
Gilles Marcou

MARCOU Gilles

Sorry for my last post, I missed some reply. I think that I understood now the problem. Using TStringList.Sort, it uses AnsiCompareStr which needs a specific widestring manager to be defined. This is done adding the unit cwstring in the program unit (the .lpr using Lazarus). A better option, if executable size is not a concern, is to use fpwidestring, but it requires fpc 2.7.1 or more. Basically, the widestring support international characters, however this support affects characters that could be thought of as Char such as the sign « = «. A good help page is there: http://wiki.freepascal.org/Character_and_string_types <http://wiki.freepascal.org/Character_and_string_types>. Please correct if I’m wrong.

I thank you all again for your kind help,
Gilles Marcou

Jonas Maebe
to MARCOU Gilles

MARCOU Gilles wrote on Tue, 08 Mar 2016:

Show quoted text 12 lines
Sorry for my last post, I missed some reply. I think that I understood now the problem. Using TStringList.Sort, it uses AnsiCompareStr which needs a specific widestring manager to be defined. This is done adding the unit cwstring in the program unit (the .lpr using Lazarus). A better option, if executable size is not a concern, is to use fpwidestring, but it requires fpc 2.7.1 or more. Basically, the widestring support international characters, however this support affects characters that could be thought of as Char such as the sign « = «. A good help page is there: http://wiki.freepascal.org/Character_and_string_types <http://wiki.freepascal.org/Character_and_string_types>. Please correct if I’m wrong.

That's indeed correct!

Jonas