Lazarus中文社区

 找回密码
 立即注册(注册审核可向QQ群索取)

QQ登录

只需一步,快速开始

Lazarus IDE and 组件 下载地址版权申明
查看: 1824|回复: 0

longstrings on 问题

[复制链接]

该用户从未签到

发表于 2013-5-24 10:08:29 | 显示全部楼层 |阅读模式
翻译:longstrings on 编译开关
出处:http://free-pascal-lazarus.98908 ... work-td4029606.html

Free Pascal - Lazarus
Login  Register

[Lazarus] LongString does not work?
[lazarus] LongString 不工作?

         Classic                List                Threaded
16 messages   Options
Xiangrong Fang Reply | Threaded | More      
Mar 03, 2013; 4:35pm [Lazarus] LongString does not work?

96 posts
96个回复

Hi All,
大家好,

This does not work:
这个代码不工作:

  TConfiguration = record
    DataFolder: string[MaxPathLen];
  end

编译错误信息: 字符串长度必须在1-255之间
Error: string length must be a value from 1 to 255

I already have this on the top of my uinit file: {$mode objfpc}{$H+}{$LONGSTRINGS ON}  
我已经将这句放到我的单元文件的顶上了:{$mode objfpc}{$H+}{$LONGSTRINGS ON}

工作环境:Lazarus 1.0.6/FPC2.6.0 on Linux 3.5/x86_64
Working with Lazarus 1.0.6/FPC2.6.0 on Linux 3.5/x86_64

Any hint please? Thanks!
请给出任何提示?谢谢!
--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

Remove Ads
Sven Barth Reply | Threaded | More      
Mar 03, 2013; 5:34pm Re: [Lazarus] LongString does not work?

872 posts
On 03.03.2013 09:35, Xiangrong Fang wrote: (中国人:方祥荣)

> Hi All,
>
> This does not work:
>
>    TConfiguration = record
>      DataFolder: string[MaxPathLen];
>    end
>
> Error: string length must be a value from 1 to 255
>
> I already have this on the top of my uinit file: {$mode
> objfpc}{$H+}{$LONGSTRINGS ON}
>
> Working with Lazarus 1.0.6/FPC2.6.0 on Linux 3.5/x86_64
>
> Any hint please? Thanks!
... [show rest of quote]

---------这是第一个回复

The "String[...]" declaration always declares a ShortString and those
can have only 1 to 255 characters. An AnsiString does not need the
"[...]", because it has always variable length.

"String[...]"声明总是定义一个短字符串类型(ShortString),并且他的长度为
1..255个字符(字节),一个ansiString类型不需要这个[...],因为他总是变长的。

Side note: {$H+} and {$LONGSTRINGS ON} is redundant, both mean the same
(though {$H+} is more commonly used).
另外:{$H+}编译开关和{$LONGSTRINGS ON}是一样的。

Regards,
敬上
Sven
赛文

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Xiangrong Fang Reply | Threaded | More       ------楼主回复 (中国人:方祥荣)
Mar 03, 2013; 5:57pm Re: [Lazarus] LongString does not work?

96 posts

Ok, My purpose is to write the record into stream, so I cannot use variable length. Now I use an array [0..MaxPathLen] of Char.
好吧,我的目地是写一个记录到流里面,所以我不能使用变长类型,但我现在要用array [0..MaxPathLen]这个字符数组(windows定义的路径长度)

--------------赛文.巴氏 回复
2013/3/3 Sven Barth <[hidden email]>
On 03.03.2013 09:35, Xiangrong Fang wrote:
Hi All,

This does not work:

   TConfiguration = record
     DataFolder: string[MaxPathLen];
   end

Error: string length must be a value from 1 to 255

I already have this on the top of my uinit file: {$mode
objfpc}{$H+}{$LONGSTRINGS ON}

Working with Lazarus 1.0.6/FPC2.6.0 on Linux 3.5/x86_64

Any hint please? Thanks!

The "String[...]" declaration always declares a ShortString and those can have only 1 to 255 characters. An AnsiString does not need the "[...]", because it has always variable length.

Side note: {$H+} and {$LONGSTRINGS ON} is redundant, both mean the same (though {$H+} is more commonly used).

Regards,
Sven


--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus


--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Sven Barth Reply | Threaded | More    赛文.巴氏 回复第2次   
Mar 03, 2013; 6:17pm Re: [Lazarus] LongString does not work?

872 posts
On 03.03.2013 10:57, Xiangrong Fang wrote:
> Ok, My purpose is to write the record into stream, so I cannot use
> variable length. Now I use an array [0..MaxPathLen] of Char.

If you want to write a complete record to stream (and not write it's
elements manually) you should declare your record as "packed" as only
then the records are guaranteed to be the same on different plattforms
(with the exception of different endianess).

如果你象写一个记录到流(不想手动写其元素),你可能需要声明你的记录为packed类型。
并且保证在不同平台上有一样的结果。
举例

E.g.

=== code begin ===

type
   TConfiguration = packed record
     //
   end;

=== code end ===

See also here: http://community.freepascal.org/docs-html/ref/refsu15.html

Regards,
Sven

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Xiangrong Fang Reply | Threaded | More      
Mar 03, 2013; 8:49pm Re: [Lazarus] LongString does not work?

96 posts
Hi Sven,

{$mode objfpc}{$H+}
  TConfiguration = packed record
      DataFolder: string;
  end;

does not work, but:

  TConfiguration = packed record
      DataFolder: array [0..MaxPathLen] of Char;
  end;

worked.  My save procedure is:

function SaveParams(var Buffer; Count: Integer; FileName: string): Boolean;
var
  fs: TFileStream;
begin
  Result := False;
  if not ForceDirectories(ExtractFilePath(FileName)) then Exit;
  try
    fs := TFileStream.Create(FileName, fmCreate);
    try
      fs.Write(Buffer, Count);
      Result := True;
    finally
      fs.Free;
    end;
  except
  end;
end;

It is called on the finalization section of config.pas:

SaveParams(cfg, SizeOf(cfg), cfn);  
//cfg is TConfgiruation, cfn is the filename.

The symptoms of error are:
1. The DataFolder value is not saved to configuration file, although file saving seems succeeded.
2. There are weird access violations, e.g. on exiting or on occasions that I try to manipulate the configuration at runtime (RunError(203) was reported).

Anything that I did wrong? or, AnsiString is not supported this way anyway?

2013/3/3 Sven Barth <[hidden email]>
On 03.03.2013 10:57, Xiangrong Fang wrote:
Ok, My purpose is to write the record into stream, so I cannot use
variable length. Now I use an array [0..MaxPathLen] of Char.

If you want to write a complete record to stream (and not write it's elements manually) you should declare your record as "packed" as only then the records are guaranteed to be the same on different plattforms (with the exception of different endianess).

E.g.

=== code begin ===

type
  TConfiguration = packed record
    //
  end;

=== code end ===

See also here: http://community.freepascal.org/docs-html/ref/refsu15.html


Regards,
Sven

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus


--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Jürgen Hestermann Reply | Threaded | More      
Mar 03, 2013; 9:11pm Re: [Lazarus] LongString does not work?

184 posts

Am 2013-03-03 13:49, schrieb Xiangrong Fang:
Hi Sven,
{$mode objfpc}{$H+}
  TConfiguration = packed record
      DataFolder: string;
  end;
does not work, but:

A (Ansi)string in {$H+} mode is just a pointer (to the characters of the string). So sizeof(DataFolder)=4 (or 8) in all cases. There is no room for the string unless you configure it with SetLength(DataFolder,MaxPathLen). But even then the record does not store the characters. It only stores the pointer to the string:

DataFolder = pointer
DataFolder[1] = DataFolder^[1] = first character of the string.

There is an automatic dereferenciation that allows to write DataFolder[x] although the logic would require DataFolder^[1].




--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Sven Barth Reply | Threaded | More      
Mar 03, 2013; 9:23pm Re: [Lazarus] LongString does not work?

872 posts
In reply to this post by Xiangrong Fang
On 03.03.2013 13:49, Xiangrong Fang wrote:

> Hi Sven,
>
> {$mode objfpc}{$H+}
>    TConfiguration = packed record
>        DataFolder: string;
>    end;
>
> does not work, but:
>
>    TConfiguration = packed record
>        DataFolder: array [0..MaxPathLen] of Char;
>    end;
>
> worked.  My save procedure is:
>
> function SaveParams(var Buffer; Count: Integer; FileName: string): Boolean;
> var
>    fs: TFileStream;
> begin
>    Result := False;
>    if not ForceDirectories(ExtractFilePath(FileName)) then Exit;
>    try
>      fs := TFileStream.Create(FileName, fmCreate);
>      try
>        fs.Write(Buffer, Count);
>        Result := True;
>      finally
>        fs.Free;
>      end;
>    except
>    end;
> end;
>
> It is called on the finalization section of config.pas:
>
> SaveParams(cfg, SizeOf(cfg), cfn);
> //cfg is TConfgiruation, cfn is the filename.
>
> The symptoms of error are:
> 1. The DataFolder value is not saved to configuration file, although
> file saving seems succeeded.
> 2. There are weird access violations, e.g. on exiting or on occasions
> that I try to manipulate the configuration at runtime (RunError(203) was
> reported).
>
> Anything that I did wrong? or, AnsiString is not supported this way anyway?
... [show rest of quote]

No, AnsiString is not supported in this way. As Jürgen wrote it's
basically a pointer to the string data and not a static array of the
string data. And the write and read procedures of TStream (but also the
file I/O) will write the record's memory as is and thus the value of the
pointer will be written in case of AnsiString.

Regards,
Sven


--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Xiangrong Fang Reply | Threaded | More      
Mar 03, 2013; 9:26pm Re: [Lazarus] LongString does not work?

96 posts
In reply to this post by Jürgen Hestermann
A (Ansi)string in {$H+} mode is just a pointer (to the characters of the string). So sizeof(DataFolder)=4 (or 8) in all cases. There is no room for the string unless

I guess this is the cause, but then there is no need to specify "packed" if I just use array of char.

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Sven Barth Reply | Threaded | More      
Mar 03, 2013; 9:34pm Re: [Lazarus] LongString does not work?

872 posts
On 03.03.2013 14:26, Xiangrong Fang wrote:
> A (Ansi)string in {$H+} mode is just a pointer (to the characters of the
> string). So sizeof(DataFolder)=4 (or 8) in all cases. There is no room
> for the string unless
>
> I guess this is the cause, but then there is no need to specify "packed"
> if I just use array of char.

The "packed" should always be used if you want to read/write data. Only
then you can be sure that the memory layout of the record is correct.
Otherwise padding bytes will be added. Consider the following record:

=== example begin ===

type
   TMyRecord = record
     b: Byte;
     i: LongInt;
     w: Word;
   end;

=== example end ===

The size of this record will be 12, because between b and i and after w
padding bytes are added. While if you add "packed" the size will be 7
and the fields will directly follow after each other.

The memory layout of non-packed records is not guaranteed to stay the
same between FPC versions! It could be for example that we find a bug in
the code that generates the memory layout of a record and then suddenly
you can no longer read in files that were written by a version of your
program compiled with the older compiler. For "packed" there is the
guarantee though that the layout will stay the same.

Regards,
Sven

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Bart Reply | Threaded | More      
Mar 03, 2013; 9:48pm Re: [Lazarus] LongString does not work?

356 posts
In reply to this post by Xiangrong Fang
On 3/3/13, Xiangrong Fang <[hidden email]> wrote:


>   TConfiguration = packed record
>       DataFolder: array [0..MaxPathLen] of Char;
>   end;
>
> worked.  My save procedure is:
>
> function SaveParams(var Buffer; Count: Integer; FileName: string): Boolean;
> var
>   fs: TFileStream;
> begin
>   Result := False;
>   if not ForceDirectories(ExtractFilePath(FileName)) then Exit;
>   try
>     fs := TFileStream.Create(FileName, fmCreate);
>     try
>       fs.Write(Buffer, Count);
>       Result := True;
>     finally
>       fs.Free;
>     end;
>   except
>   end;
> end;
>
> It is called on the finalization section of config.pas:
>
> SaveParams(cfg, SizeOf(cfg), cfn);
> //cfg is TConfgiruation, cfn is the filename.
>
... [show rest of quote]

Are you only writing strings (and/or integers and/or booleans)  to the
configuration file?
If so, wouldn't it be just easier to use a TIniFile for that?

Bart

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Xiangrong Fang Reply | Threaded | More      
Mar 03, 2013; 9:59pm Re: [Lazarus] LongString does not work?

96 posts
I was using an INI file, but record make things a lot easier.

2013/3/3 Bart <[hidden email]>
On 3/3/13, Xiangrong Fang <[hidden email]> wrote:


>   TConfiguration = packed record
>       DataFolder: array [0..MaxPathLen] of Char;
>   end;
>
> worked.  My save procedure is:
>
> function SaveParams(var Buffer; Count: Integer; FileName: string): Boolean;
> var
>   fs: TFileStream;
> begin
>   Result := False;
>   if not ForceDirectories(ExtractFilePath(FileName)) then Exit;
>   try
>     fs := TFileStream.Create(FileName, fmCreate);
>     try
>       fs.Write(Buffer, Count);
>       Result := True;
>     finally
>       fs.Free;
>     end;
>   except
>   end;
> end;
>
> It is called on the finalization section of config.pas:
>
> SaveParams(cfg, SizeOf(cfg), cfn);
> //cfg is TConfgiruation, cfn is the filename.
>

Are you only writing strings (and/or integers and/or booleans)  to the
configuration file?
If so, wouldn't it be just easier to use a TIniFile for that?

Bart

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus


--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
leledumbo Reply | Threaded | More      
Mar 03, 2013; 11:41pm Re: [Lazarus] LongString does not work?

Administrator
169 posts
> I was using an INI file, but record make things a lot easier.

If you use TIniFile, you don't have to worry about saving and restoring values. It's much easier than writing your own saving/restoring procedure.
Luca Olivetti Reply | Threaded | More      
Mar 04, 2013; 3:32am Re: [Lazarus] LongString does not work?

73 posts
In reply to this post by Sven Barth
Al 03/03/13 14:34, En/na Sven Barth ha escrit:

> For "packed" there is the
> guarantee though that the layout will stay the same.

Are you sure? Does the same guarantee apply to bitpacked?
Lately I've become lazy, and instead of manually decoding data (bits,
bytes, words) read from a device, I'm relying on packed/bitpacked
records, but I wasn't sure that upgrading the compiler wouldn't break my
code.

Bye
--
Luca Olivetti
Wetron Automation Technology http://www.wetron.es
Tel. +34 935883004  Fax +34 935883007

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Sven Barth Reply | Threaded | More      
Mar 04, 2013; 4:52am Re: [Lazarus] LongString does not work?

872 posts
On 03.03.2013 20:32, Luca Olivetti wrote:

> Al 03/03/13 14:34, En/na Sven Barth ha escrit:
>
>> For "packed" there is the
>> guarantee though that the layout will stay the same.
>
> Are you sure? Does the same guarantee apply to bitpacked?
> Lately I've become lazy, and instead of manually decoding data (bits,
> bytes, words) read from a device, I'm relying on packed/bitpacked
> records, but I wasn't sure that upgrading the compiler wouldn't break my
> code.
... [show rest of quote]

For "packed" it is guaranteed (*), because this is the whole purpose of
this modifier, for "bitpacked" it is not. It just tells the compiler to
pack the record as densly as possible, but depending on the platform
this might not be possible.

(*) the only exception for this is the JVM platform, because there the
file I/O mechanism of Pascal is not supported

Regards,
Sven

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Luca Olivetti Reply | Threaded | More      
Mar 05, 2013; 12:10am Re: [Lazarus] LongString does not work?

73 posts
Al 03/03/13 21:52, En/na Sven Barth ha escrit:

> On 03.03.2013 20:32, Luca Olivetti wrote:
>> Al 03/03/13 14:34, En/na Sven Barth ha escrit:
>>
>>> For "packed" there is the
>>> guarantee though that the layout will stay the same.
>>
>> Are you sure? Does the same guarantee apply to bitpacked?
>> Lately I've become lazy, and instead of manually decoding data (bits,
>> bytes, words) read from a device, I'm relying on packed/bitpacked
>> records, but I wasn't sure that upgrading the compiler wouldn't break my
>> code.
>
> For "packed" it is guaranteed (*), because this is the whole purpose of
> this modifier, for "bitpacked" it is not. It just tells the compiler to
> pack the record as densly as possible, but depending on the platform
> this might not be possible.
... [show rest of quote]

At the moment I don't care about the platform, only about different
(newer) versions of the compiler.
Currently , with 2.6.0, bitpacked under win32 gives me the correct
layout (I have to adjust endianness for words/dwords but individual bit
fields are where they should be).
Can I be sure that 2.6.2 (and later version) won't break my code?

Bye
--
Luca Olivetti
Wetron Automation Technology http://www.wetron.es
Tel. +34 935883004  Fax +34 935883007


--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Sven Barth Reply | Threaded | More      
Mar 05, 2013; 5:03am Re: [Lazarus] LongString does not work?

872 posts
Am 04.03.2013 17:10, schrieb Luca Olivetti:

> Al 03/03/13 21:52, En/na Sven Barth ha escrit:
>> On 03.03.2013 20:32, Luca Olivetti wrote:
>>> Al 03/03/13 14:34, En/na Sven Barth ha escrit:
>>>
>>>> For "packed" there is the
>>>> guarantee though that the layout will stay the same.
>>> Are you sure? Does the same guarantee apply to bitpacked?
>>> Lately I've become lazy, and instead of manually decoding data (bits,
>>> bytes, words) read from a device, I'm relying on packed/bitpacked
>>> records, but I wasn't sure that upgrading the compiler wouldn't break my
>>> code.
>> For "packed" it is guaranteed (*), because this is the whole purpose of
>> this modifier, for "bitpacked" it is not. It just tells the compiler to
>> pack the record as densly as possible, but depending on the platform
>> this might not be possible.
> At the moment I don't care about the platform, only about different
> (newer) versions of the compiler.
> Currently , with 2.6.0, bitpacked under win32 gives me the correct
> layout (I have to adjust endianness for words/dwords but individual bit
> fields are where they should be).
> Can I be sure that 2.6.2 (and later version) won't break my code?
... [show rest of quote]
I can only give you a guarantee for packed. For bitpacked it's
documented that you shouldn't rely on the binary format.

Regards,
Sven

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

Remove Ads
&#171; Return to Free Pascal - Lazarus  |  20 views
Powered by Nabble        Edit this page

回复

使用道具 举报

*滑块验证:

本版积分规则

QQ|手机版|小黑屋|Lazarus中国|Lazarus中文社区 ( 鄂ICP备16006501号-1 )

GMT+8, 2025-5-3 01:31 , Processed in 0.049274 second(s), 9 queries , Redis On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表